<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Tam Nguyen on Medium]]></title>
        <description><![CDATA[Stories by Tam Nguyen on Medium]]></description>
        <link>https://medium.com/@tam159?source=rss-aa8262612fcd------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*j_ZcoH_hssmMc-FKrorjrA.jpeg</url>
            <title>Stories by Tam Nguyen on Medium</title>
            <link>https://medium.com/@tam159?source=rss-aa8262612fcd------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 31 May 2026 17:32:59 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@tam159/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[9 Methods to Enhance the Performance of a LLM RAG Application]]></title>
            <link>https://tam159.medium.com/9-methods-to-enhance-the-performance-of-a-llm-rag-application-3bedfdc842e1?source=rss-aa8262612fcd------2</link>
            <guid isPermaLink="false">https://medium.com/p/3bedfdc842e1</guid>
            <category><![CDATA[rags]]></category>
            <category><![CDATA[llm]]></category>
            <category><![CDATA[generative-ai-tools]]></category>
            <category><![CDATA[nlp]]></category>
            <category><![CDATA[mlops]]></category>
            <dc:creator><![CDATA[Tam Nguyen]]></dc:creator>
            <pubDate>Mon, 20 Nov 2023 02:48:25 GMT</pubDate>
            <atom:updated>2023-11-22T02:59:58.138Z</atom:updated>
            <content:encoded><![CDATA[<p>It is easy to prototype your first LLM RAG (Retrieval Augmented Generation) application, e.g. using this <a href="https://github.com/langchain-ai/chat-langchain">chat-langchain</a> template with below architecture.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*HuiLSJsc1_P3j0UxVyTXag.png" /><figcaption>Image by <a href="https://github.com/langchain-ai/langchain">LangChain</a></figcaption></figure><p>But it is hard to make it work well. In this article, I gather and share some approaches to enhance the performance of the LLM RAG application.</p><p>For more details, please refer to references I mention in each section.</p><h3>1. Store message histories and user feedbacks</h3><p>Chat histories and user feedbacks are important for the application analytics. We will use them later in a next session.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/981/1*fU12LkK8X5l9AnmkK3rTJw.gif" /></figure><p>In an above schema, 1 collection should have multiple embeddings. 1 user can have many chat sessions, and in each chat session, we store the messages (between human and AI) and their analytical information such as generated questions (condense questions or questions after query transformations), retrieved chunks and corresponding distance scores, user feedback, .etc.</p><h3>2. Start evaluating your application</h3><p>A naive RAG app can have some challenges, e.g.: bad retrieval (low precision, low recall, outdated information), bad response generation (hallucination, irrelevance, toxicity/bias), .etc.</p><p>Before improving it, we need a way to measure its performance. We can use the following <a href="https://github.com/explodinggradients/ragas">ragas</a> metrics for the evaluation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qd6PP9N4OpYUQk12ypKlcQ.png" /></figure><p>Because some scores need ground_truth, there are 2 ways to create the labeled evaluation dataset:</p><ul><li>Human-annotated labeled dataset: we can use some real questions and answers that users give good feedback from the first method chat_analysis table.</li><li>Generated labeled dataset (good for cold start): Prompt GPT-4 Turbo to generate questions from each chunk or multiple chunks to get pairs of question &amp; doc chunks. Then run above pairs of question &amp; context through GPT-4 Turbo to generate answer.</li></ul><p>Eventually we can run through this labeled dataset with above pre-defined metrics and use GPT-4 Turbo as an evaluator/judge.</p><p>For a better observation, we should also use some LLMOps platforms such as <a href="https://smith.langchain.com/">LangSmith</a>, <a href="https://github.com/mlflow/mlflow">MLflow</a> or integrate <a href="https://github.com/confident-ai/deepeval">DeepEval</a> in CI/CD pipelines.</p><h3>3. <a href="https://python.langchain.com/docs/modules/data_connection/retrievers/multi_vector">Multi-vector retriever</a></h3><p>When splitting documents for retrieval, there are often conflicting desires:</p><ul><li>We may want to have small chunks, so that their embeddings can most accurately reflect their meaning. If too long, then the embeddings can lose meaning.</li><li>We also want to have long enough documents that the contexts are retained. Separating the document many times by separators and chunk_size sometimes breaks the context unexpectedly. It&#39;s also hard to combine the chunks in a right order to form the meaningful document for a prompt context.</li></ul><p>Below approaches allow us to balance precise embeddings and context retention by splitting documents into smaller chunks for embedding but retrieving larger text information or even the whole original document for the prompt context, since many LLM models nowadays support long context window, e.g. GPT-4 Turbo supports 128,000 tokens.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xhZaO26OZpZVTz6FGYf5IQ.png" /><figcaption><em>Image by </em><a href="https://theaiedge.io"><em>TheAiEdge</em></a></figcaption></figure><h4><a href="https://python.langchain.com/docs/modules/data_connection/retrievers/parent_document_retriever">Parent Document Retriever</a></h4><ul><li>Instead of indexing entire documents, data is divided into smaller chunks, referred to as Parent and Child documents.</li><li>Child documents are indexed for better representation of specific concepts, while parent documents are retrieved to ensure context retention.</li><li>Sometimes, the full documents can be too big to retrieve them as is. In that case, first split the raw documents into larger chunks, and then split them into smaller chunks. We then index the smaller chunks, but on retrieval we retrieve the larger chunks (but still not the full documents).</li></ul><h4>Hypothetical Questions</h4><ul><li>Documents are processed to generate potential questions they might answer.</li><li>These questions are then indexed for better representation of specific concepts, while parent documents are retrieved to ensure context retention.</li></ul><h4>Summaries</h4><ul><li>Instead of indexing the entire document, a summary of the document is created and indexed.</li><li>Similarly, the parent document is retrieved in the application.</li></ul><h3>4. Query transformations</h3><p>Because the original query can not be always optimal to retrieve for the LLM, especially in the real world. The user often doesn’t provide the full context and thinks about the question from a specific angle.</p><p>Query transformation deals with transformations of the user’s question before passing to the embedding model. Below are a few variations of query transform methods and their sample prompt implementation. They are all using an LLM to generate a new or multiple new queries.</p><ol><li><a href="https://github.com/langchain-ai/langchain/blob/master/cookbook/rewrite.ipynb">Rewrite-Retrieve-Read</a></li><li><a href="https://python.langchain.com/docs/templates/hyde">Hypothetical Document Embeddings (HyDE)</a></li><li><a href="https://smith.langchain.com/hub/langchain-ai/weblangchain-search-query">Follow-up question to condensed/standalone one</a></li><li><a href="https://github.com/langchain-ai/langchain/blob/master/cookbook/rag_fusion.ipynb">RAG Fusion</a></li><li><a href="https://github.com/langchain-ai/langchain/blob/master/cookbook/stepback-qa.ipynb">Step-Back Prompting</a></li><li><a href="https://python.langchain.com/docs/modules/data_connection/retrievers/MultiQueryRetriever">Multi Query Retrieval / Expansion</a></li></ol><p>We can also combine multiple query transformation techniques to get the best result e.g.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/671/1*FgNFJOrJ4oRGmn1B1RDe3A.gif" /></figure><h3>5. Query construction for retrieval optimization</h3><h4><a href="https://python.langchain.com/docs/modules/data_connection/retrievers/self_query">Self-querying</a></h4><p>Do you remember a metadata column in an above embedding table? We can include additional information such as author, genre, rating, the date it was written, …, and any information about the document beyond the text itself. We can define a schema and store the metadata in a structured way alongside the vector representation.</p><p>With the database metadata schema, we use LLM to construct a structured query from the question to filter the document chunks. At the same time, the question is also converted into its vector representation for the similarity search. This kind of hybrid retrieval approaches are likely to become more and more common when RAG becomes a more widely adopted strategy.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/514/1*8KdjOPv0vAMU5EYOhd6nxg.gif" /></figure><h4><a href="https://python.langchain.com/docs/modules/data_connection/retrievers/time_weighted_vectorstore">Time-weighted retriever</a></h4><p>In some cases, the information contained in the documents is only relevant if it is recent enough. In the context of a time-weighted retriever, the data is retrieved based on the hybrid score between semantic similarity and the age of the document. The algorithm for scoring it can be:</p><pre>semantic_similarity + (1.0 - decay_rate) ^ hours_passed</pre><h4><a href="https://blog.langchain.dev/query-construction">Other query constructions</a></h4><ul><li><a href="https://blog.langchain.dev/llms-and-sql">Text-to-SQL</a></li><li><a href="https://github.com/langchain-ai/langchain/blob/master/cookbook/retrieval_in_sql.ipynb">Text-To-SQL+semantic</a></li><li><a href="https://python.langchain.com/docs/use_cases/graph/graph_cypher_qa">Text-to-Cypher</a></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BtMPZmUSkc1aKLkwSO4bVQ.png" /><figcaption>Image by <a href="https://github.com/langchain-ai/langchain">LangChain</a></figcaption></figure><h3>6. Document selection optimization</h3><h4><a href="https://python.langchain.com/docs/integrations/retrievers/cohere-reranker">Re-ranking</a></h4><p>After first-stage retrieval (lexical/keyword-based search or semantic/embedding-based search), doing re-ranking as a second stage to rank retrieved documents using relevance scores.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*D9mtw2MlolAUYuZYr9Bfiw.png" /><figcaption><em>Image by </em><a href="https://cohere.com"><em>Cohere</em></a></figcaption></figure><h4><a href="https://python.langchain.com/docs/modules/model_io/prompts/example_selectors/mmr">Maximal Marginal Relevance (MMR)</a></h4><p>Sometimes we retrieve more than we actually need, there can be similar documents capturing the same information. The MMR metric penalizes redundant information.</p><p>The reranking is an iterative process where we measure the similarity of the vectors to the query and the similarity of the vectors to the vectors we have already re-ranked, end up with a vector similar to the query but dissimilar to the vectors we already reranked.</p><h3>7. <a href="https://python.langchain.com/docs/use_cases/summarization">Context Optimization</a></h3><p>Now that we have selected the correct documents to answer the question, we need to figure out how we will pass data as context for the LLM to answer the question.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zrqpzBNG0AJfU2Qvo6hpuQ.png" /><figcaption>Image by <a href="https://github.com/langchain-ai/langchain">LangChain</a></figcaption></figure><ul><li><a href="https://python.langchain.com/docs/modules/chains/document/stuff">Stuffing</a> is the simplest method to pass data to the language model. It concatenates the text of those documents and pass it to the prompt.</li><li><a href="https://python.langchain.com/docs/modules/chains/document/map_reduce">MapReduce</a> implements a multi-stage summarization. It is a technique for summarizing large pieces of text by first summarizing smaller chunks of text and then combining those summaries into a single summary. Instead of summarization, we can also iterate through the documents to extract the information likely to answer the question.</li><li><a href="https://python.langchain.com/docs/modules/chains/document/refine">Refine</a> method is an alternative method to deal with large document summarization. It works by first running an initial prompt on a small chunk of data, generating some output. Then, for each subsequent document, the output from the previous document is passed in along with the new document, and the LLM is asked to refine the output based on the new document.</li><li><a href="https://python.langchain.com/docs/modules/chains/document/map_rerank">Map-rerank</a> strategy iterates through each document and tries to answer the question along with a score on how well the question was answered. We can then pick the answer with the highest score.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/202078b529c0068095c17f2f534c93d6/href">https://medium.com/media/202078b529c0068095c17f2f534c93d6/href</a></iframe><h3>8. <a href="https://blog.langchain.dev/semi-structured-multi-modal-rag">Multimodal RAG</a></h3><p>When dealing with semi-structured or unstructured data e.g. tables, text, and images, we might need multimodal LLM and/or multimodal embeddings, below are some options:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*f8CAL8qyHcsqnrW6g21aRg.png" /><figcaption>Image by <a href="https://github.com/langchain-ai/langchain">LangChain</a></figcaption></figure><ol><li>Use multimodal embeddings (such as CLIP) to embed images and text together. Retrieve either using similarity search, but simply link to images in a docstore. Pass raw images and text chunks to a multimodal LLM for synthesis.</li><li>Use a multimodal LLM (such as GPT4-V, LLaVA, or FUYU-8b) to produce text summaries from images. Embed and retrieve text summaries using a text embedding model. And, again, reference raw text chunks or tables from a docstore for answer synthesis by the LLM. Then exclude image from the docstore, instead pass image text summary to LLM or use a multi-modal LLM for synthesis, with raw image and raw table, text.</li></ol><h3>9. <a href="https://python.langchain.com/docs/modules/agents">Agents</a></h3><p>Last but not least, you may not only build the RAG app to answer questions from documents, we can have multiple tools to augment the LLM app, or <a href="https://python.langchain.com/docs/expression_language/how_to/routing">route question between multiple datastores</a>. An agent uses the LLM to choose a sequence of actions to take to solve a problem.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/521/1*KBPfeX5Q2rLj_s94Suxqbw.gif" /></figure><p>The Agent can consist of some key components:</p><ul><li>The Agent Core: This is the central component of the agent responsible for making decisions. It is powered by the LLM and a prompt that includes the agent’s personality, background context, and prompting strategies.</li><li>Tools and Toolkits: Tools are functionalities that the agent can access and utilize to perform specific tasks. Toolkits are collections of related tools that work together to accomplish specific objectives. There are two important design considerations around tools: giving the agent access to the right tools and describing the tools in a way that is most helpful to the agent.</li></ul><p>There are some types of agents we should first start with:</p><ul><li><a href="https://python.langchain.com/docs/modules/agents/agent_types/react">ReAct</a></li><li><a href="https://python.langchain.com/docs/modules/agents/agent_types/openai_functions_agent">OpenAI functions</a></li><li><a href="https://python.langchain.com/docs/modules/agents/agent_types/openai_assistants">OpenAI assistants</a></li></ul><h3>Conclusion</h3><p>I suggest to read all above methods and other <a href="https://blog.langchain.dev/applying-openai-rag">RAG Strategies from Open AI</a>, then pick the ones that are most relevant to your use case. You can also combine multiple approaches to get the best result. For example, the first architecture can be turned to a below one.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*obfksZk4ifkduKWWyNuV_Q.gif" /></figure><p>If you find this article useful, please give it a clap and share it with your friends. Also kindly checkout a <a href="https://github.com/tam159/generative_ai">generative_ai</a> repo that contains some generative AI techniques and follow me in <a href="https://www.linkedin.com/pulse/9-methods-enhance-performance-llm-rag-application-tam-nguyen-ooljc">LinkedIn</a>.</p><p>Thanks for reading!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3bedfdc842e1" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Book Review: Simplifying Data Engineering and Analytics with Delta]]></title>
            <link>https://tam159.medium.com/book-review-simplifying-data-engineering-and-analytics-with-delta-cb7865dd5b46?source=rss-aa8262612fcd------2</link>
            <guid isPermaLink="false">https://medium.com/p/cb7865dd5b46</guid>
            <category><![CDATA[data-lakehouse]]></category>
            <category><![CDATA[data-mesh]]></category>
            <category><![CDATA[book-review]]></category>
            <category><![CDATA[delta-lake]]></category>
            <category><![CDATA[spark]]></category>
            <dc:creator><![CDATA[Tam Nguyen]]></dc:creator>
            <pubDate>Sun, 24 Jul 2022 04:16:49 GMT</pubDate>
            <atom:updated>2023-03-15T04:44:30.296Z</atom:updated>
            <content:encoded><![CDATA[<p>Building data engineering and analytics platform is hard. It does not only contains OLAP systems and data pipelines, but also many aspects that we need to care such as and data modeling, data governance, data observability, data quality and data lineage, .etc.</p><p>We also maybe sometimes confused in managing both data warehouse and data lake, at this point I tent to the Lakehouse architecture. I wrote articles about <a href="https://www.linkedin.com/pulse/road-lakehouse-part-1-delta-lake-data-pipeline-overview-tam-nguyen/">building Delta Lake data pipeline with code</a>, but in order to build the comprehensive Lakehouse platform including all data components that I mentioned above, I recommend reading the book: “<a href="https://www.amazon.com/Simplifying-Data-Engineering-Analytics-Delta/dp/1801814864">Simplifying Data Engineering and Analytics with Delta</a>”.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*flORT1F0qHETQ_rFnbK3uw.png" /><figcaption>Author: Anindita Mahapatra — a Solutions Architect at Databricks</figcaption></figure><h4>What is the book about?</h4><p>There are 3 sessions in the book:</p><ul><li>Session 1: Data Engineering Principles</li></ul><p>It talks about some big data design patterns and best practices for data modeling. Delta as a file format is also introduced here with its advantages over pure Parquet.</p><p>There are some useful theoretical data system designs that may help you in the interviews 😸 such as Spark distributed processing, stages of data modeling, metadata management, data formats, Lakehouse characteristics, .etc.</p><ul><li>Session 2: Building end-to-end Delta Pipelines</li></ul><p>Firstly, it shares differences between Lambda and Kappa architectures, then introduces Spark unifying batch and streaming with Delta, which includes Spark structured streaming code examples and windows, watermarking , .etc concepts.</p><p>Secondly, it walks through some common data pattern scenarios like handling CDC , SCD in Delta Lake with merge queries. It also explains how the Delta table works with transaction log, commits, checkpoint, .etc, and how to optimize tables with Z-order and file size.</p><p>Thirdly, this chapter gives some useful tips for exploratory data analysis (EDA) such as data profiling, data drift, data anonymity, statistical analysis, class imbalance, data skew and main types of joins, .etc.</p><p>The next thing are machine learning pipelines and challenges of ML development. Then we are introduced the ML model, MLOps and how Delta helps in feature engineering, model training, inferencing and monitoring pipelines.</p><p>The last thing in this chapter are DaaS and DaaP (data as a product) concepts in the context of a data mesh with some illustrations of Delta with unstructured data and Delta sharing.</p><ul><li>Session 3: Delta Pipeline Operation in Production</li></ul><p>There are some factors that we need to care in the production environment: scalability, high availability, RTO and RPO in different DR strategies. This chapter shares how Delta helps in DR. Then it talks about the data quality guarantee with validation examples in DLT. It also mentions continuous training (CT) and continuous monitoring (CM) which are additional steps beside CI/CD in ML pipelines.</p><p>Performance and cost are also big concerns in the data platform and Delta can optimize these things by compaction, data skipping, ZOrder, partition pruning, dynamic file pruning, optimum file size, delta caching, .etc.</p><p>Last but not least, provisioning a multi-tenant infrastructure for data democratization via policies and processes, capacity planning, monitoring and data sharing are the things that we need to take a look as DevOps/MLOps engineers.</p><h4>Summary</h4><p>This book is easy to read for all data practitioners, it shares real world use cases with demonstrations by PySpark example code blocks and the latest features of Delta Lake. It’s also well-structured by going through basic theoretical data principles to building, optimizing and maintaining practical data pipelines and machine learning pipelines.</p><p>You can preorder the book <a href="https://www.amazon.com/Simplifying-Data-Engineering-Analytics-Delta/dp/1801814864">here</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=cb7865dd5b46" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Road to Lakehouse — Part 2: Ingest and process data from Kafka with CDC and Delta Lake’s CDF]]></title>
            <link>https://tam159.medium.com/road-to-lakehouse-part-2-ingest-and-process-data-from-kafka-with-cdc-and-delta-lakes-cdf-318708468a47?source=rss-aa8262612fcd------2</link>
            <guid isPermaLink="false">https://medium.com/p/318708468a47</guid>
            <category><![CDATA[change-data-feed]]></category>
            <category><![CDATA[delta-live-tables]]></category>
            <category><![CDATA[databricks]]></category>
            <category><![CDATA[delta-lake]]></category>
            <category><![CDATA[structured-streaming]]></category>
            <dc:creator><![CDATA[Tam Nguyen]]></dc:creator>
            <pubDate>Sun, 23 Jan 2022 14:58:12 GMT</pubDate>
            <atom:updated>2022-01-23T15:09:44.566Z</atom:updated>
            <content:encoded><![CDATA[<h3>Road to Lakehouse — Part 2: Ingest and process data from Kafka with CDC and Delta Lake’s CDF</h3><p>This is a second part of the Data Lakehouse and data pipelines implementation in the Delta Lake. Source code GitHub repositories are at the end of this article. For a high level pipeline architecture, please take a look at the first part.</p><p><a href="https://www.linkedin.com/pulse/road-lakehouse-part-1-delta-lake-data-pipeline-overview-tam-nguyen">Road to Lakehouse — Part 1</a>: Delta Lake data pipeline overview</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NihRQMwvRaB1jaxJutwNTQ.png" /><figcaption>Delta Lake Data Pipeline</figcaption></figure><h3>Raw Ingestion</h3><p>I divide the Kafka data into 2 categories: <em>event</em> data which comes from the backend application and <em>cdc</em> data which is generated by Debezium. Below is a main PySpark job.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d33a7c08d092d7eb3f379a4fcce20599/href">https://medium.com/media/d33a7c08d092d7eb3f379a4fcce20599/href</a></iframe><h4>Ingest data from Kafka</h4><p>To ingest the data from Kafka, we just need to specify credentials and topic name.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/70555aff2641e3d4f9d8fe4beade7c2e/href">https://medium.com/media/70555aff2641e3d4f9d8fe4beade7c2e/href</a></iframe><h4>Process the Kafka data</h4><p>We need to get the schema of the topic first.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/9d74c94fabfee184f21340516ce8675b/href">https://medium.com/media/9d74c94fabfee184f21340516ce8675b/href</a></iframe><p>In case of CDC, below is an example of MongoDB payload schema.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f6cfad2967194d73b20690dc4d7bed3e/href">https://medium.com/media/f6cfad2967194d73b20690dc4d7bed3e/href</a></iframe><p>Once we have the schema, it is easy to get the data in plain texts.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c7f545d43bf465761bf96436bac9d923/href">https://medium.com/media/c7f545d43bf465761bf96436bac9d923/href</a></iframe><h4>Load the processed data into a raw area</h4><p>Eventually let write the stream to a delta table in the raw zone. Spark stores Kafka offsets in checkpoint locations for failure recoveries.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a2c453470100cad596ee1b5371d770dd/href">https://medium.com/media/a2c453470100cad596ee1b5371d770dd/href</a></iframe><h3>Refined zone</h3><p>While there are several ways to transform data inside the Delta Lake between different layers such as using dbt or Delta Live Tables, we can leverage the built-in property in delta tables which is the Change Data Feed (CDF) without any additional cost to merge changes to the next area in near real-time.</p><p>Below is a main PySpark job to extract changes from the raw table then process, load them into the refined table.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3a68102e7a29e64f28e75fe4f595c919/href">https://medium.com/media/3a68102e7a29e64f28e75fe4f595c919/href</a></iframe><h4>Read change feed from raw tables</h4><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8634510f8eeeaa48e5927c0f24122854/href">https://medium.com/media/8634510f8eeeaa48e5927c0f24122854/href</a></iframe><h4>Process the CDF</h4><p>We can do some transformations like flattening a nested json or exploding an array before loading the data into the refined layer.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ef2d76accbd1a47f50b0298131b9451c/href">https://medium.com/media/ef2d76accbd1a47f50b0298131b9451c/href</a></iframe><h3>Conclusion</h3><p>Above streaming data pipeline is a good starting point to build further business level tables. In your real project you might need to do more complicated operations like upserting or joining multiple tables, but the general idea of using Spark structured streaming and CDF is still valid. There are many more things to do with the Delta Lake like using SQLAlchemy ORM to query data, visualizing data with Streamlit and building ML workflows with Databricks Feature Store, AutoML, MLflow, .etc, hopefully we can discuss more about them in the next article.</p><h3>Source code</h3><ul><li><a href="https://github.com/tam159/delta-lake-library">GitHub - tam159/delta-lake-library: Delta lake common libraries to ingest, process and load data into Databricks lakehouse with Spark jobs</a></li><li><a href="https://github.com/tam159/delta-lake-pipeline">GitHub - tam159/delta-lake-pipeline: Delta lake pipelines in Databricks lakehouse with Spark structured streaming and batching jobs</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=318708468a47" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ML workflow with Airflow, MLflow and SageMaker]]></title>
            <link>https://tam159.medium.com/ml-workflow-with-airflow-mlflow-and-sagemaker-ad076e5f614b?source=rss-aa8262612fcd------2</link>
            <guid isPermaLink="false">https://medium.com/p/ad076e5f614b</guid>
            <category><![CDATA[machine-learning-workflow]]></category>
            <category><![CDATA[airflow]]></category>
            <category><![CDATA[mlops]]></category>
            <category><![CDATA[mlflow]]></category>
            <category><![CDATA[sagemaker]]></category>
            <dc:creator><![CDATA[Tam Nguyen]]></dc:creator>
            <pubDate>Thu, 26 Aug 2021 03:18:02 GMT</pubDate>
            <atom:updated>2021-09-04T05:46:15.900Z</atom:updated>
            <content:encoded><![CDATA[<p>Regarding MLOps, there are many tools to support data, workflow, model, .etc management.</p><h3>And we can start with a simple ML workflow using following platforms</h3><ul><li>Airflow for the run orchestration.</li><li>MLflow for the experiment tracking and organization.</li><li>SageMaker for job training, hyperparameter tuning, model serving and production monitoring.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vIeCJsvg2trAhsycpcK69A.png" /><figcaption>ML workflow (Image by author)</figcaption></figure><p>About the Airflow and MLflow setups, we can deploy them in any infrastructure (K8s, ECS, .etc) with meta data stored in RDS.</p><p>We will use Airflow as a scheduler so we don’t need a complex worker architecture, all the computation jobs will be handled by SageMaker and other AWS services.</p><p>MLflow provided 4 main features related to ML lifecycle including central model registry, model deployment, project code management and experiment tracking.</p><blockquote>Starting from determining what is observed, what should be predicted and how performance and error metrics need to be optimized.</blockquote><h4>The business problem is framed as a machine learning problem, follow by some steps</h4><ol><li>Data acquisition: ingesting data from sources including data collection, data integration and data quality checking.</li><li>Data pre-processing: handling missing data, outliers, long tails, .etc.</li><li>Feature engineering: running experiments with different features, adding, removing and changing features.</li><li>Data transformation: standardizing data, converting data format compatible with training algorithms.</li><li>Job training: training’s parameters, metrics, .etc are tracked in the MLflow. We can also run SageMaker Hyperparameter Optimization with many training jobs then search the metrics and params in the MLflow for a comparison with minimal effort to find the best version of a model.</li><li>Model evaluation: analyzing model performance based on predicted results on test data.</li><li>If business goals are met, the model will be registered in the SageMaker Inference Models. We can also register the model in the MLflow.</li><li>Getting predictions in any of the following ways:</li></ol><ul><li>Using SageMaker Batch Transform to get predictions for an entire dataset.</li><li>Setting up a persistent endpoint to get one prediction at a time using SageMaker Inference Endpoints.</li></ul><p>9. Monitoring and debugging the workflow, re-training with a data augmentation.</p><h4>For the data processing, feature engineering and model evaluation, we can use several AWS services</h4><ol><li>EMR: providing a Hadoop ecosystem cluster including pre-installed Spark, Flink, .etc. We should use a transient cluster to process the data and terminate it when all done.</li><li>Glue job: providing a server-less Apache Spark, Python environments. Glue’ve supported Spark 3.1 since 2021 Aug.</li><li>SageMaker Processing jobs: running in containers, there are many prebuilt images supporting data science. It also supports Spark 3.</li></ol><h4>Data accessing</h4><ul><li>All data stored in S3 can be queried via Athena with metadata from Glue data catalog.</li><li>We can also ingest the data into SageMaker Feature Store in batches directly to the offline store.</li></ul><h3>Sample workflow</h3><ul><li>Dataset: <a href="https://www.kaggle.com/manjeetsingh/retaildataset">Kaggle Retail Data Analytics</a></li><li>For full stages, please refer to this <a href="https://github.com/tam159/mlops">GitHub repo</a></li></ul><h4>Training and hyperparameter tuning jobs</h4><ul><li>AWS SageMaker is cost-effective with EC2 spot instances.</li><li>In order to log the training parameters and metrics in MLflow, we should use the SageMaker script mode with a below sample training script.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bf05f62024a66c97166a7585e42289c6/href">https://medium.com/media/bf05f62024a66c97166a7585e42289c6/href</a></iframe><ul><li>And we can specify the SageMaker estimator and hyperparameter ranges for the tuning jobs.</li></ul><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e6f58f26d6becbb5d4b3192db59e4b9d/href">https://medium.com/media/e6f58f26d6becbb5d4b3192db59e4b9d/href</a></iframe><ul><li>Then let’s take a look at different models’ metrics with different parameters in the MLflow.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*71AOOXjUU0XEph3z0YVJcQ.png" /><figcaption>MLflow experiment tracking (Image by author)</figcaption></figure><h3>Conclusion</h3><p>This basic ML workflow could be a good starting point, then we can expand it by adding other stuffs such as data versioning, CI/CD process, online feature store, .etc.</p><p>For more details, please take a look at a below GitHub repo, and welcome all constructive comments!</p><h3>References</h3><p><a href="https://github.com/tam159/mlops">GitHub - tam159/mlops: ML Ops: Machine Learning Operations</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ad076e5f614b" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>