paint-brush
बड़े भाषा मॉडल के साथ अपने dbt प्रोजेक्ट को कैसे बढ़ाएंद्वारा@klimmy
563 रीडिंग
563 रीडिंग

बड़े भाषा मॉडल के साथ अपने dbt प्रोजेक्ट को कैसे बढ़ाएं

द्वारा Kliment Merzlyakov15m2024/06/02
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

आप अपने dbt वातावरण में रहते हुए, LLM का उपयोग करके अपने टेक्स्ट डेटा के लिए सामान्य प्राकृतिक भाषा प्रसंस्करण कार्यों (वर्गीकरण, भावना विश्लेषण, आदि) को $10 प्रति 1M पंक्तियों के सस्ते दाम पर स्वचालित रूप से हल कर सकते हैं (यह कार्य और मॉडल पर निर्भर करता है)। निर्देश, विवरण और कोड नीचे दिए गए हैं
featured image - बड़े भाषा मॉडल के साथ अपने dbt प्रोजेक्ट को कैसे बढ़ाएं
Kliment Merzlyakov HackerNoon profile picture
0-item
1-item



संक्षेप में

आप अपने dbt वातावरण में रहते हुए, LLM का उपयोग करके अपने टेक्स्ट डेटा के लिए सामान्य प्राकृतिक भाषा प्रसंस्करण कार्यों (वर्गीकरण, भावना विश्लेषण, आदि) को $10 प्रति 1M पंक्तियों के सस्ते दाम पर स्वचालित रूप से हल कर सकते हैं (यह कार्य और मॉडल पर निर्भर करता है)। निर्देश, विवरण और कोड नीचे दिए गए हैं


यदि आप dbt को अपने परिवर्तन परत के रूप में उपयोग कर रहे हैं, तो आपके सामने ऐसी स्थिति आ सकती है जब आप असंरचित पाठ डेटा से सार्थक जानकारी निकालना चाहें। इस तरह के डेटा में ग्राहक समीक्षाएँ, शीर्षक, विवरण, Google Analytics स्रोत/माध्यम आदि शामिल हो सकते हैं। आप उन्हें समूहों में वर्गीकृत करना या भावनाएँ और स्वर प्राप्त करना चाह सकते हैं।


संभावित समाधान होंगे

  • डीबीटी प्रवाह के बाहर मशीन लर्निंग मॉडल लागू करें (या एलएलएम को बुलाएं)
  • CASE WHEN कथनों का उपयोग करके dbt मॉडल के अंदर सरल वर्गीकरण परिभाषित करें
  • श्रेणियों को पहले से ही पूर्वनिर्धारित करें और उन्हें या तो अपने कच्चे डेटाबेस स्तर पर अपलोड करें या डीबीटी सीड कार्यक्षमता का लाभ उठाएं


चूंकि पायथन डीबीटी मॉडल विकसित हो रहे हैं, इसलिए एक और समाधान है: आप इन प्राकृतिक भाषा प्रसंस्करण कार्यों को अपने डीबीटी वातावरण के अंदर डीबीटी मॉडल के रूप में रख सकते हैं।


यदि यह आपके लिए मददगार हो सकता है, तो अपने dbt प्रोजेक्ट में OpenAI API का उपयोग करने के तरीके पर नीचे चरण-दर-चरण मार्गदर्शिका देखें। आप GitHub रिपॉजिटरी से कोड और डेटा सैंपल लेकर अपने परिवेश में इस गाइड से सब कुछ पुन: पेश कर सकते हैं (अंत में लिंक देखें)।

वातावरण सेट अप करें

यदि आपके पास पहले से ही कोई dbt प्रोजेक्ट और डेटा है या आप परिणामों को पुन: प्रस्तुत नहीं करना चाहते हैं, तो (4) पर जाएँ या इस अनुभाग को पूरी तरह से छोड़ दें। अन्यथा, आपको निम्नलिखित की आवश्यकता होगी:


  1. dbt प्रोजेक्ट सेट अप करेंआधिकारिक दस्तावेज़

    1. आप आसानी से GitHub से इस गाइड के लिए तैयार किए गए एक को क्लोन कर सकते हैं।

    2. अपनी profiles.yml फ़ाइल बनाना/अपडेट करना न भूलें।


  2. डेटाबेस सेट करें । मैंने स्नोफ्लेक का इस्तेमाल किया। दुर्भाग्य से, इसका कोई निःशुल्क संस्करण नहीं है, लेकिन वे 30-दिन का निःशुल्क परीक्षण प्रदान करते हैं, हालाँकि

    1. वर्तमान में, dbt पायथन मॉडल केवल स्नोफ्लेक, डेटाब्रिक्स और बिगक्वेरी (कोई PostgreSQL नहीं) के साथ काम करते हैं। इसलिए, यह ट्यूटोरियल उनमें से किसी के लिए भी काम करना चाहिए, हालाँकि कुछ विवरण भिन्न हो सकते हैं


  3. स्रोत डेटा तैयार करें

    1. डेटासेट के रूप में, मैंने TidyTuesday रिपॉजिटरी में प्रकाशित एक आर पैकेज मेटाडेटा का उपयोग किया।

      1. आप इसे यहाँ से डाउनलोड कर सकते हैं। डेटासेट का विवरणयहाँ है
      2. वैकल्पिक रूप से, आप यहां मेरे रिपॉजिटरी से एक हल्के संस्करण का उपयोग कर सकते हैं
    2. इसे अपने डेटाबेस पर अपलोड करें.

    3. अपने डेटाबेस और स्कीमा नामों से मिलान करने के लिए dbt प्रोजेक्ट में source.yml फ़ाइल को अपडेट करें।


  4. OpenAI API कुंजी प्राप्त करें

    1. आधिकारिक दस्तावेज़ों से त्वरित आरंभ निर्देशों का पालन करें.

    2. ध्यान दें: यह मुफ़्त नहीं है, लेकिन इसके लिए आपको भुगतान करना होगा। इसलिए, परीक्षण 10-पंक्ति डेटासेट के साथ, आपके प्रयोगों के दौरान आपसे $1 से ज़्यादा शुल्क नहीं लिया जाएगा।

    3. अतिरिक्त सावधानी बरतने के लिए, खर्च की सीमा निर्धारित करें।


  5. स्नोफ्लेक में बाह्य एक्सेस एकीकरण सेट अप करें

    1. यह तभी लागू होता है जब आप स्नोफ्लेक का उपयोग करते हैं।
    2. यदि ऐसा नहीं किया जाता है, तो dbt पायथन मॉडल इंटरनेट पर किसी भी API (OpenAI API सहित) तक नहीं पहुंच पाएंगे।
    3. आधिकारिक निर्देशों का पालन करें.
    4. इस एकीकरण में OpenAI API कुंजी संग्रहीत करें.

श्रेणियों की सूची बनाएं

सबसे पहले, यदि आप वर्गीकरण कार्य हल कर रहे हैं, तो आपको अपने LLM प्रॉम्प्ट में उपयोग करने के लिए श्रेणियों (उर्फ कक्षाओं) की आवश्यकता होगी। मूल रूप से, आप कहेंगे: "मेरे पास इन श्रेणियों की एक सूची है, क्या आप परिभाषित कर सकते हैं कि यह पाठ किस श्रेणी से संबंधित है?"


यहां कुछ विकल्प हैं:

  1. पूर्वनिर्धारित श्रेणियों की सूची मैन्युअल रूप से बनाएं

    1. यदि आपको स्थिर और पूर्वानुमानित श्रेणियों की आवश्यकता है तो यह उपयुक्त है।

    2. यहां "अन्य" जोड़ना न भूलें, ताकि अनिश्चितता की स्थिति में एलएलएम के पास ये विकल्प उपलब्ध हों।

    3. अपने प्रॉम्प्ट में LLM से पूछें कि जब भी वह "अन्य" श्रेणी का उपयोग करे तो वह एक श्रेणी का नाम सुझाए।

    4. डेटाबेस की रॉ परत पर या अपने dbt प्रोजेक्ट में CSV के रूप में एक पूर्वनिर्धारित सूची अपलोड करें ( dbt seed उपयोग करके)।


  2. अपने डेटा का एक नमूना LLM को दें, और उसे N श्रेणियां बनाने को कहें।

    1. पिछले दृष्टिकोण जैसा ही, लेकिन हमें सूची बनाने में सहायता मिल रही है।

    2. यदि आप GPT का उपयोग करते हैं, तो पुनरुत्पादन के लिए बीज का उपयोग करना बेहतर है।


  3. पूर्वनिर्धारित श्रेणियों के बिना आगे बढ़ें, और LLM को चलते-फिरते काम करने दें।

    1. इससे कम पूर्वानुमानित परिणाम सामने आ सकते हैं।

    2. साथ ही, यदि आप यादृच्छिकता की सीमा के साथ ठीक हैं तो यह पर्याप्त है।

    3. GPT उपयोग के मामले में, यदि आपको पुनः चलाने की आवश्यकता हो तो भिन्न परिणामों से बचने के लिए तापमान = 0 रखना बेहतर होता है।


इस ब्लॉग पोस्ट में, मैं तीसरे विकल्प का प्रयोग करूंगा।

OpenAI API को कॉल करने के लिए dbt पायथन मॉडल बनाएं

अब, आइए इस पोस्ट के मुख्य भाग पर जाएं और एक dbt मॉडल बनाएं जो अपस्ट्रीम टेबल से नया टेक्स्ट डेटा लेगा, इसे OpenAI API में फीड करेगा, और श्रेणी को टेबल में सेव करेगा।


जैसा कि ऊपर बताया गया है, मैं R पैकेज डेटासेट का उपयोग करने जा रहा हूँ। डेटा विश्लेषण में R एक अत्यधिक लोकप्रिय प्रोग्रामिंग भाषा है। इस डेटासेट में CRAN प्रोजेक्ट से R पैकेज के बारे में जानकारी है, जैसे कि संस्करण, लाइसेंस, लेखक, शीर्षक, विवरण, आदि। हम title फ़ील्ड में रुचि रखते हैं, क्योंकि हम प्रत्येक पैकेज के लिए उसके शीर्षक के आधार पर एक श्रेणी बनाने जा रहे हैं।


  1. मॉडल के लिए आधार तैयार करें

    • dbt कॉन्फ़िगरेशन को dbt.config(...) विधि के माध्यम से पारित किया जा सकता है।


    • dbt.config में अतिरिक्त तर्क हैं, उदाहरण के लिए, packages एक पैकेज आवश्यकता है।


    • dbt पायथन मॉडल अपस्ट्रीम मॉडल dbt.ref('...') या dbt.source('...') संदर्भित कर सकता है


    • इसे एक DataFrame लौटाना होगा। आपका डेटाबेस इसे एक टेबल के रूप में सहेज लेगा।


     import os import openai import pandas as pd COL_TO_CATEGORIZE = 'title' def model(dbt, session): import _snowflake dbt.config( packages=['pandas', 'openai'], ) df = dbt.ref('package').to_pandas() df.drop_duplicates(subset=[COL_TO_CATEGORIZE], inplace=True) return df
  2. OpenAI API से कनेक्ट करें

    • हमें secrets और external_access_integrations dbt.config में पास करना होगा। इसमें वह secret reference होगा जो आपके Snowflake External Access Integration में संग्रहीत है।


    • नोट: यह सुविधा कुछ दिन पहले ही जारी की गई थी और यह केवल बीटा dbt संस्करण 1.8.0-b3 में उपलब्ध है

     dbt.config( packages=['pandas', 'openai'], secrets={'openai_key': 'openai_key', 'openai_org': 'openai_org'}, external_access_integrations=['openai_external_access_integration'], ) client = openai.OpenAI( api_key=_snowflake.get_generic_secret_string('openai_key'), organization=_snowflake.get_generic_secret_string('openai_org'), )
  3. डीबीटी मॉडल को वृद्धिशील बनाएं, और पूर्ण रिफ्रेश को बंद करें।

    • ओपनएआई एपीआई की लागत कम रखने के लिए यह भाग आवश्यक है।
    • यह एक ही पाठ को कई बार वर्गीकृत करने से रोकेगा।
    • अन्यथा, आप हर बार dbt run निष्पादित करते समय OpenAI को पूरा डेटा भेजेंगे, जो दिन में कई बार हो सकता है।
    • हम materialized='incremental' , incremental_strategy='append' , full_refresh = False dbt.config में जोड़ रहे हैं
    • अब, पूर्ण स्कैन केवल पहले dbt रन के लिए होगा, और बाद के रन के लिए (चाहे वृद्धिशील या पूर्ण-रिफ्रेश हो), यह केवल डेल्टा को वर्गीकृत करेगा।
    • यदि आप अतिरिक्त सावधानी बरतना चाहते हैं, तो आप अद्वितीय प्रविष्टियों की संख्या को कम करने के लिए अपने डेटा को थोड़ा पूर्व-प्रसंस्करण कर सकते हैं, लेकिन बहुत अधिक पूर्व-प्रसंस्करण से बचें क्योंकि LLM प्राकृतिक भाषा के साथ बेहतर काम करते हैं।
     dbt.config( materialized='incremental', incremental_strategy='append', full_refresh = False, packages=['pandas', 'openai'], secrets={'openai_key': 'openai_key', 'openai_org': 'openai_org'}, external_access_integrations=['openai_external_access_integration'], ) if dbt.is_incremental: pass


  4. वृद्धिशीलता तर्क जोड़ें

    • वृद्धिशील रन पर (हमारे सेटअप के कारण, इसका मतलब है कि पहले रन को छोड़कर किसी भी रन पर), हमें पहले से वर्गीकृत सभी शीर्षकों को हटाना होगा।
    • हम इसे केवल dbt.this उपयोग करके कर सकते हैं। सामान्य वृद्धिशील मॉडल के समान।
     if dbt.is_incremental: categorized_query = f''' SELECT DISTINCT "{ COL_TO_CATEGORIZE }" AS primary_key FROM { dbt.this } WHERE "category" IS NOT NULL ''' categorized = [row.PRIMARY_KEY for row in session.sql(categorized_query).collect()] df = df.loc[~df[COL_TO_CATEGORIZE].isin(categorized), :]
  5. OpenAI API को बैचों में कॉल करें

    • लागत कम करने के लिए, OpenAI API को डेटा को बैचों में भेजना बेहतर है।
    • सिस्टम प्रॉम्प्ट उस टेक्स्ट से 5 गुना बड़ा हो सकता है जिसे हमें वर्गीकृत करने की आवश्यकता है। यदि हम प्रत्येक शीर्षक के लिए सिस्टम प्रॉम्प्ट को अलग से भेजते हैं, तो इससे दोहराए जाने वाले चीज़ों के लिए टोकन का उपयोग बहुत अधिक हो जाएगा।
    • हालाँकि, बैच बड़ा नहीं होना चाहिए। बड़े बैच के साथ, GPT कम स्थिर परिणाम देना शुरू कर देता है। मेरे प्रयोगों से, बैच आकार = 5 काफी अच्छा काम करता है।
    • इसके अतिरिक्त, यह सुनिश्चित करने के लिए कि प्रतिक्रिया प्रासंगिक आकार से अधिक न हो, मैंने max_tokens प्रतिबंध जोड़ा।
     BATCH_SIZE = 5 n_rows = df.shape[0] categories = [None for idx in range(n_rows)] for idx in range(0, n_rows, BATCH_SIZE): df_sliced = df.iloc[idx:idx+BATCH_SIZE, :] user_prompt = f'```{ "|".join(df_sliced[COL_TO_CATEGORIZE].to_list()) }```' chat_completion = client.chat.completions.create( messages=[ {'role': 'system', 'content': SYSTEM_PROMPT}, {'role': 'user', 'content': user_prompt} ], model='gpt-3.5-turbo', temperature=0, max_tokens=10*BATCH_SIZE + 2*BATCH_SIZE, ) gpt_response = chat_completion.choices[0].message.content gpt_response = [category.strip() for category in gpt_response.split('|')] categories[idx:idx + len(gpt_response)] = gpt_response df['category'] = categories df.dropna(subset=['category'], inplace=True)


  6. एलएलएम के लिए एक प्रॉम्प्ट के बारे में बात करने का समय आ गया है। मुझे यही मिला:

आपको ``` कोष्ठकों में CRAN R पैकेज शीर्षकों की सूची प्रदान की जाएगी। शीर्षकों को "|" चिह्न से अलग किया जाएगा। प्रत्येक शीर्षक के लिए एक श्रेणी बनाएँ। केवल "|" चिह्न से अलग किए गए श्रेणी नाम लौटाएँ।


  • निर्देश सीधे मुद्दे पर रखें।
  • SQL इंजेक्शन से बचने के लिए ``` तकनीक का उपयोग करें।
  • परिणाम प्रारूप पर स्पष्ट रहें। मेरे मामले में, मैंने इनपुट और आउटपुट दोनों के लिए विभाजक के रूप में "|" मांगा था


  1. अंतिम डीबीटी मॉडल कोड

     import os import openai import pandas as pd SYSTEM_PROMPT = '''You will be provided a list of CRAN R package titles in ``` brackets. Titles will be separated by "|" sign. Come up with a category for each title. Return only category names separated by "|" sign. ''' COL_TO_CATEGORIZE = 'title' BATCH_SIZE = 5 def model(dbt, session): import _snowflake dbt.config( materialized='incremental', incremental_strategy='append', full_refresh = False, packages=['pandas', 'openai'], secrets={'openai_key': 'openai_key', 'openai_org': 'openai_org'}, external_access_integrations=['openai_external_access_integration'], ) client = openai.OpenAI( api_key=_snowflake.get_generic_secret_string('openai_key'), organization=_snowflake.get_generic_secret_string('openai_org'), ) df = dbt.ref('package').to_pandas() df.drop_duplicates(subset=[COL_TO_CATEGORIZE], inplace=True) if dbt.is_incremental: categorized_query = f''' SELECT DISTINCT "{ COL_TO_CATEGORIZE }" AS primary_key FROM { dbt.this } WHERE "category" IS NOT NULL ''' categorized = [row.PRIMARY_KEY for row in session.sql(categorized_query).collect()] df = df.loc[~df[COL_TO_CATEGORIZE].isin(categorized), :] n_rows = df.shape[0] categories = [None for idx in range(n_rows)] for idx in range(0, n_rows, BATCH_SIZE): df_sliced = df.iloc[idx:idx+BATCH_SIZE, :] user_prompt = f'```{ "|".join(df_sliced[COL_TO_CATEGORIZE].to_list()) }```' chat_completion = client.chat.completions.create( messages=[ {'role': 'system', 'content': SYSTEM_PROMPT}, {'role': 'user', 'content': user_prompt} ], model='gpt-3.5-turbo', temperature=0, max_tokens=10*BATCH_SIZE + 2*BATCH_SIZE, ) gpt_response = chat_completion.choices[0].message.content gpt_response = [category.strip() for category in gpt_response.split('|')] categories[idx:idx + len(gpt_response)] = gpt_response df['category'] = categories df.dropna(subset=['category'], inplace=True) return df

लागत अनुमान

OpenAI API मूल्य निर्धारण यहाँ सूचीबद्ध है। वे अनुरोधित और लौटाए गए टोकन की संख्या के लिए शुल्क लेते हैं। टोकन आपके अनुरोध में वर्णों की संख्या से संबंधित एक उदाहरण है। किसी दिए गए टेक्स्ट के लिए टोकन की संख्या का मूल्यांकन करने के लिए ओपन-सोर्स पैकेज हैं। उदाहरण के लिए, टिकटोकन । यदि आप इसे मैन्युअल रूप से मूल्यांकन करना चाहते हैं, तो आपको आधिकारिक OpenAI टोकनाइज़र यहाँ जाना होगा।


हमारे डेटासेट में, ~18K शीर्षक हैं। मोटे तौर पर, यह 320K इनपुट टोकन (180K शीर्षक और 140K सिस्टम प्रॉम्प्ट यदि हम बैच आकार = 5 का उपयोग करते हैं) और 50K आउटपुट टोकन के बराबर है। मॉडल के आधार पर, पूर्ण स्कैन की लागत होगी:


  1. GPT-4 Turbo : $4.7 . मूल्य निर्धारण: इनपुट: $10 / 1M टोकन; आउटपुट: $30 / 1M टोकन.
  2. GPT-4 : $12.6. मूल्य निर्धारण: इनपुट: $30 / 1M टोकन; आउटपुट: $60 / 1M टोकन.
  3. GPT-3.5 Turbo : $0.2. मूल्य निर्धारण: इनपुट: $0.5 / 1M टोकन; आउटपुट: $1.5 / 1M टोकन.

परिणाम

डीबीटी मॉडल ने कमाल का काम किया। मैंने बिना किसी अंतराल के सभी 18K पैकेजों को सफलतापूर्वक वर्गीकृत किया। मॉडल लागत-कुशल साबित हुआ और कई डीबीटी रन के खिलाफ सुरक्षित रहा।


मैंने Tableau Public पर परिणाम डैशबोर्ड यहाँ प्रकाशित किया है। आप इसके साथ खेलने के लिए स्वतंत्र हैं, डेटा डाउनलोड करें, और इसके ऊपर जो चाहें बना सकते हैं।

मुझे कुछ दिलचस्प विवरण मिले:


  • शीर्ष-1 श्रेणी Data Visualization (1,190 पैकेज, या 6%) है। मुझे लगता है कि यह विज़ुअलाइज़ेशन टूल के रूप में R की लोकप्रियता को साबित करता है, खासकर शाइनी, प्लॉटली और अन्य जैसे पैकेजों के साथ।


  • 2023 में शीर्ष दो बढ़ती श्रेणियां Data Import और Data Processing थीं। ऐसा लगता है कि R का उपयोग डेटा-प्रोसेसिंग टूल के रूप में अधिक किया जाने लगा।


  • शीर्ष 30 श्रेणियों में सबसे बड़ी साल-दर-साल वृद्धि 2019 में Natural Language Processing में हुई। प्रसिद्ध पेपर "अटेंशन इज़ ऑल यू नीड" के दो साल बाद और GPT-1 रिलीज़ के आधे साल बाद :)

आगे के विचार

  1. हम एक वैकल्पिक दृष्टिकोण का उपयोग कर सकते हैं - GPT एम्बेडिंग

    • यह बहुत सस्ता है.

    • लेकिन इसमें इंजीनियरिंग की अधिक आवश्यकता है, क्योंकि वर्गीकरण का काम आपको स्वयं ही करना होगा (मेरे साथ बने रहें, क्योंकि मैं अगले पोस्ट में इस विकल्प पर चर्चा करने जा रहा हूँ)।


  2. निश्चित रूप से, इस भाग को dbt से हटाकर क्लाउड फ़ंक्शन या आपके द्वारा उपयोग किए जाने वाले किसी भी इंफ्रास्ट्रक्चर में डालना समझदारी है। साथ ही, यदि आप इसे dbt के अंतर्गत रखना चाहते हैं - तो यह पोस्ट आपके लिए है।


  3. मॉडल में कोई भी तर्क जोड़ने से बचें। इसे एक काम करना चाहिए - LLM को कॉल करें और परिणाम को सेव करें। इससे आपको इसे फिर से चलाने से बचने में मदद मिलेगी।


  4. संभावना अधिक है कि आप अपने dbt प्रोजेक्ट में कई वातावरण का उपयोग कर रहे हैं। आपको सावधान रहना चाहिए और प्रत्येक पुल अनुरोध पर प्रत्येक डेवलपर वातावरण में इस मॉडल को बार-बार चलाने से बचना चाहिए।

    • ऐसा करने के लिए, आप if dbt.config.get("target_name") == 'dev' के साथ तर्क को शामिल कर सकते हैं


  5. सीमांकक के साथ प्रतिक्रिया अस्थिर हो सकती है।

    • उदाहरण के लिए, GPT आपकी अपेक्षा से कम तत्व लौटा सकता है, और प्रारंभिक शीर्षकों को श्रेणियों की सूची में मैप करना कठिन होगा।

    • इस पर काबू पाने के लिए, JSON आउटपुट की आवश्यकता के लिए अपने अनुरोध में response_format={ "type": "json_object" } जोड़ें। आधिकारिक दस्तावेज़ देखें।

    • JSON आउटपुट के साथ, आप प्रॉम्प्ट में {"title": "category"} प्रारूप में उत्तर प्रदान करने के लिए कह सकते हैं, और फिर इसे अपने प्रारंभिक मानों पर मैप कर सकते हैं।

    • ध्यान रखें कि यह अधिक महंगा होगा, क्योंकि इससे प्रतिक्रिया का आकार बढ़ जाएगा।

    • अजीब बात यह है कि जब मैंने GPT 3.5 टर्बो के लिए JSON पर स्विच किया तो वर्गीकरण की गुणवत्ता में नाटकीय रूप से गिरावट आई।


  6. स्नोफ्लेक में एक विकल्प है - कॉर्टेक्स.कम्प्लीट() फ़ंक्शन का उपयोग करना। dbt ब्लॉग पर जोएल लैब्स द्वारा लिखी गई एक बेहतरीन पोस्ट देखें।


बस इतना ही! मुझे बताइए आप क्या सोचते हैं।

लिंक

पूरा कोड GitHub पर: लिंक

Tableau पब्लिक डैशबोर्ड: लिंक

TidyTuesday R डेटासेट:लिंक