使用 DSPy 和 Langfuse 提升你的 LLM 应用程序
原文towardsdatascience.com/supercharge-your-llm-apps-using-dspy-and-langfuse-f83c02ba96a1?sourcecollection_archive---------2-----------------------#2024-10-07轻松构建生产级 LLM 应用https://medium.com/Rghv_Bali?sourcepost_page---byline--f83c02ba96a1--------------------------------https://towardsdatascience.com/?sourcepost_page---byline--f83c02ba96a1-------------------------------- Raghav Bali·发表于Towards Data Science ·阅读时间 12 分钟·2024 年 10 月 7 日–https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/03fee566222b05ecc08e045cd78395f5.png图片来源Glen Carrie 在UnsplashLLM 的崛起大型语言模型LLM已成为一种变革性力量彻底改变了我们与信息的互动和处理方式。这些强大的人工智能模型能够理解和生成类似人类的文本已经在多个领域找到了应用从聊天机器人和虚拟助手到内容创作和数据分析。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/ba0872bec49d5fb2b3f7ca3b00afd991.png常规的基于提示的开发工作流。来源作者然而构建和维护高效的 LLM 驱动应用程序并非没有挑战。提示工程即为 LLM 制定精确指令的艺术可能是一个耗时且反复迭代的过程。由于这些模型具有固有的“黑箱”特性调试和故障排除 LLM 的行为也可能变得复杂。此外了解 LLM 应用程序的性能和成本影响对于优化和可扩展性至关重要这是任何生产环境设置的关键组件。LLM 生态系统LLM 的生态系统仍处于初期阶段。为了解决其中的一些挑战许多创新工具和框架正在开发中。来自斯坦福大学的DSPy就是一种正式化 LLM 应用开发的独特尝试。另一方面Langfuse则作为一个解决方案出现旨在简化和操作化 LLM 应用维护的各个方面。简而言之DSPY提供了一个模块化和可组合的框架用于构建 LLM 应用程序抽象化了提示工程的复杂性使开发人员能够专注于应用程序的核心逻辑。Langfuse提供了一个全面的可观测性平台帮助 LLM 应用程序提供关于模型性能、成本和用户交互的深刻洞察。通过结合 DSPy 和 Langfuse开发人员可以释放 LLM 的全部潜力构建强大、可扩展且具有深刻洞察力的应用程序从而提供卓越的用户体验。利用 DSPy 释放大语言模型LLM的潜力语言模型是极其复杂的机器能够从一个非常大的潜在空间中检索和重组信息。为了引导这个搜索并获得期望的响应我们在很大程度上依赖复杂、冗长且脆弱的提示有时这些提示对于特定的 LLM 来说非常具体。作为一个开放的研究领域各个团队从不同的角度工作以抽象化和加速 LLM 系统的快速开发。DSPy 就是一个针对 LLM 提示和权重进行算法优化的框架。好吧你让我感兴趣了能告诉我更多吗DSPy 框架从深度学习框架如PyTorch中汲取灵感。例如使用 PyTorch 构建深度神经网络时我们只需使用标准层如卷积、丢弃、线性并将其与优化器如Adam连接然后进行训练而不必每次都从头开始实现这些。同样DSPy 提供了一套标准的通用模块例如ChainOfThought、Predict、优化器例如BootstrapFewShotWithRandomSearch并通过将这些组件作为层组合成一个程序来帮助我们构建系统而无需显式处理提示是不是很棒DSPy 构建块与工作流https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/490f9851fac27b4b2ff35e95ad3565ff.png图 1左DSPy 构建块包括签名Signatures、模块Modules、优化器Optimizers。(右) DSPy 程序工作流。来源作者如图 1所示DSPy 是一个类似 PyTorch/乐高积木的框架用于构建基于 LLM 的应用程序。开箱即用它包括签名这些是用于定义 DSPy 程序输入输出行为的规范。可以使用简写表示法例如“question - answer”框架会自动理解 question 是输入answer 是输出或者使用声明式规范通过 Python 类进行定义后续章节将详细介绍。模块这些是预定义组件的层用于实现强大的概念如Chain of Thought、ReAct甚至是简单的文本完成Predict。这些模块抽象了底层脆弱的提示同时仍然通过自定义组件提供可扩展性。优化器这些优化器是 DSPy 框架特有的灵感来源于 PyTorch 本身。这些优化器利用注释数据集和评估指标帮助调优/优化基于 LLM 的 DSPy 程序。数据、指标、断言和跟踪器是该框架的其他组成部分它们像粘合剂一样在背后工作丰富了整体框架。要使用 DSPy 构建应用/程序我们采用模块化且循序渐进的方法如图 1右所示。我们首先定义我们的任务以帮助我们清晰地定义程序的签名输入和输出规范。接下来我们构建一个管道程序该程序利用一个或多个抽象化的提示模块、语言模型模块以及检索模型模块。完成这些步骤后我们接着准备一些示例并结合所需的指标来评估我们的设置这些指标被优化器和断言组件用来编译一个强大的应用。使用 Langfuse 获取 LLM 洞察Langfuse 是一个 LLM 工程平台旨在帮助开发者构建、管理和优化基于 LLM 的应用。虽然它提供了托管和自托管解决方案但在本文中我们将重点介绍自托管选项使你能够完全控制自己的 LLM 基础设施。Langfuse 设置的主要亮点Langfuse 为你提供了一套强大的工具简化了 LLM 开发流程提示管理轻松版本控制和检索提示确保可重复性并促进实验。追踪通过详细的追踪信息深入了解你的 LLM 应用便于高效调试和故障排除。开箱即用的直观 UI 使团队能够标注模型交互以开发和评估训练数据集。指标跟踪重要指标如成本、延迟和令牌使用情况使你能够优化性能并控制开销。评估捕获用户反馈注释 LLM 响应甚至设置评估函数持续评估并改进你的模型。数据集管理和组织来自 LLM 应用的数据集促进进一步的微调和模型增强。轻松设置Langfuse 的自托管解决方案非常易于设置利用基于docker的架构你可以通过docker compose快速启动。这种简化的方式最小化了部署复杂性使你能够专注于构建你的 LLM 应用。框架兼容性Langfuse 与流行的 LLM 框架如LangChain、LlamaIndex以及 DSPy 无缝集成使其成为适用于各种 LLM 开发框架的多功能工具。DSPY Langfuse 的强大功能通过将 Langfuse 集成到你的 DSPy 应用中你可以解锁丰富的可观察性功能使你能够实时监控、分析和优化你的模型。将 Langfuse 集成到你的 DSPy 应用中集成过程简单涉及使用 Langfuse 的 SDK 为你的 DSPy 代码添加监控功能。importdspyfromdsp.trackers.langfuse_trackerimportLangfuseTracker# configure trackerlangfuseLangfuseTracker()# instantiate openai clientopenaidspy.OpenAI(modelgpt-4o-mini,temperature0.5,max_tokens1500)# dspy predict supercharged with automatic langfuse trackersopenai(What is DSPy?)通过 Langfuse 获得洞察一旦集成Langfuse 会提供一系列关于 DSPy 应用行为的可操作洞察基于追踪的调试跟踪 DSPY 程序的执行流程定位瓶颈并识别需要改进的地方。性能监控跟踪关键指标如延迟和令牌使用量以确保最佳的性能和成本效益。用户互动分析了解用户如何与 LLM 应用互动识别常见查询并发现优化机会。数据收集与微调收集并注解 LLM 的响应构建有价值的数据集以便进一步的微调和模型优化。用例增强DSPy 和 Langfuse 的结合在以下场景中尤为重要复杂的管道在处理涉及多个模块的复杂 DSPy 管道时Langfuse 的追踪功能对调试和理解信息流至关重要。生产环境在生产环境中Langfuse 的监控功能确保你的 LLM 应用顺利运行提前警告潜在问题同时关注相关成本。迭代开发Langfuse 的评估和数据集管理工具促进了基于数据的迭代允许你根据真实世界的使用情况不断优化你的 LLM 应用。元用例我的工作坊问答机器人为了真正展示 DSPy 与 Langfuse 强大监控能力的结合我最近将它们应用于一个独特的数据集我最近的 LLM 工作坊 GitHub 仓库。这个为期一天的工作坊包含了大量的材料帮助你入门 LLM。这个问答机器人旨在帮助参与者在工作坊期间及其后解答一系列与 NLP 和 LLM 相关的主题。这个“元”用例不仅展示了这些工具的实际应用还为我们的探索增添了一些自我反思的色彩。任务构建问答系统在本次练习中我们将利用 DSPy 构建一个问答系统该系统能够回答关于我的工作坊内容笔记本、markdown 文件等的问题。这个任务突出了 DSPy 处理和提取文本数据中信息的能力这是许多 LLM 应用中至关重要的功能。试想一下拥有一个个人 AI 助手或副驾驶能够帮助你回忆过去几周的细节、识别工作中的模式甚至挖掘被遗忘的洞察这还展示了这样的模块化设置如何轻松扩展到任何其他文本数据集几乎不需要任何努力。让我们从设置程序所需的对象开始。importosimportdspyfromdsp.trackers.langfuse_trackerimportLangfuseTracker config{LANGFUSE_PUBLIC_KEY:XXXXXX,LANGFUSE_SECRET_KEY:XXXXXX,LANGFUSE_HOST:http://localhost:3000,OPENAI_API_KEY:XXXXXX,OPENAI_BASE_URL:XXXXXX,OPENAI_PROVIDER:XXXXXX,CHROMA_DB_PATH:./chromadb/,CHROMA_COLLECTION_NAME:supercharged_workshop_collection,CHROMA_EMB_MODEL:all-MiniLM-L6-v2}# setting configos.environ[LANGFUSE_PUBLIC_KEY]config.get(LANGFUSE_PUBLIC_KEY)os.environ[LANGFUSE_SECRET_KEY]config.get(LANGFUSE_SECRET_KEY)os.environ[LANGFUSE_HOST]config.get(LANGFUSE_HOST)os.environ[OPENAI_API_KEY]config.get(OPENAI_API_KEY)# setup Langfuse trackerlangfuse_trackerLangfuseTracker(session_idsupercharger001)# instantiate language-model for DSPYllm_modeldspy.OpenAI(api_keyconfig.get(OPENAI_API_KEY),modelgpt-4o-mini)# instantiate chromadb clientchroma_emb_fnembedding_functions.\ SentenceTransformerEmbeddingFunction(model_nameconfig.get(CHROMA_EMB_MODEL))clientchromadb.HttpClient()# setup chromadb collectioncollectionclient.create_collection(config.get(CHROMA_COLLECTION_NAME),embedding_functionchroma_emb_fn,metadata{hnsw:space:cosine})一旦我们设置好了这些客户端和跟踪器就让我们快速地向我们的文档库中添加一些文档有关我如何准备这个数据集的详细操作请参阅此笔记本。# Add to collectioncollection.add(documents[vfor_,vinnb_scraper.notebook_md_dict.items()],idsdoc_ids,# must be unique for each doc)下一步是简单地将我们的 chromadb 检索器连接到 DSPy 框架。以下代码片段创建了一个 RM 对象并测试检索是否按预期工作。retriever_modelChromadbRM(config.get(CHROMA_COLLECTION_NAME),config.get(CHROMA_DB_PATH),embedding_functionchroma_emb_fn,clientclient,k5)# Test Retrievalresultsretriever_model(RLHF)forresultinresults:display(Markdown(f__Document__::{result.long_text[:100]}... \n))display(Markdown(f- __Document id__::{result.id}\n- __Document score__::{result.score}))结果看起来很有前景因为在没有任何干预的情况下Chromadb 能够获取最相关的文档。Document::# Quick Overview of RLFHThe performance of Language Models until GPT-3was kind of amazingas-is....-Documentid::6_module_03_03_RLHF_phi2-Document score::0.6174977412306334Document::# Getting Started : Text Representation ImageThe NLP domain...-Documentid::2_module_01_02_getting_started-Document score::0.8062083377747705Document::# Text Generation a target_blank hrefhttps://colab.research.google.com/github/raghavbali/llm_w ...-Documentid::3_module_02_02_simple_text_generator-Document score::0.8826038964887366Document::# Image DSPy: Beyond Promptingimg src./assets/dspy_b...-Documentid::12_module_04_05_dspy_demo-Document score::0.9200280698248913最后一步是将所有这些内容整合在一起准备一个 DSPy 程序。对于我们的简单问答用例我们准备了一个标准的 RAG 程序利用 Chromadb 作为检索器Langfuse 作为跟踪器。以下代码片段展示了开发基于 LLM 的应用程序的类似 pytorch 的方法无需担心脆弱的提示# RAG SignatureclassGenerateAnswer(dspy.Signature):Answer questions with short factoid answers.contextdspy.InputField(descmay contain relevant facts)questiondspy.InputField()answerdspy.OutputField(descoften less than 50 words)# RAG ProgramclassRAG(dspy.Module):def__init__(self,num_passages3):super().__init__()self.retrievedspy.Retrieve(knum_passages)self.generate_answerdspy.ChainOfThought(GenerateAnswer)defforward(self,question):contextself.retrieve(question).passages predictionself.generate_answer(contextcontext,questionquestion)returndspy.Prediction(contextcontext,answerprediction.answer)# compile a RAG# note: we are not using any optimizers for this examplecompiled_ragRAG()呼这不是很简单快速吗现在让我们通过几个示例问题来实际应用它。my_questions[List the models covered in module03,Brief summary of module02,What is LLaMA?]forquestioninmy_questions:# Get the prediction. This contains pred.context and pred.answer.predcompiled_rag(question)display(Markdown(f__Question__:{question}))display(Markdown(f__Predicted Answer__: _{pred.answer}_))display(Markdown(__Retrieved Contexts (truncated):__))foridx,continenumerate(pred.context):print(f{idx1}.{cont[:200]}...)print()display(Markdown(---))输出确实非常准确达到了作为此工作坊材料助手的目的能够回答问题并很好地引导参与者。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/12ca0eec049875f56d6d90960d5d0723.png图 2DSPy RAG 程序的输出。来源作者Langfuse 的优势在本文的前面部分我们讨论了 langfuse 是如何通过让我们监控 LLM 的使用情况并改进管道的其他方面来完善整个流程的。langfuse 作为跟踪工具的惊人集成通过一个简单易用的界面将所有内容在后台串联起来。在当前的设置中langfuse 仪表板呈现了我们 LLM 使用情况的快速总结。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/3a36ba9137c9c67f2dd44f0ce7d93a6e.png图 3Langfuse 仪表板。来源作者仪表板包括如追踪数量、总成本甚至令牌使用等指标这些在优化管道时非常有用。洞察与好处Langfuse 的实用性不仅仅局限于顶层的度量仪表板。它还提供了追踪级别的详细信息如图 4所示。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/f1112de13de787eefe9a218d498d391f.png图 4Langfuse 跟踪详细信息包括成本、令牌使用、提示以及模型响应。来源作者。这个界面是通往多个其他方面的门户这些方面在迭代和改进基于 LLM 的应用程序时非常有用。首先要提到的功能是基于实际使用情况准备数据集。这些数据集可用于微调 LLM、优化 DSPy 程序等。图 5展示了如何从网页 UI 本身轻松定义数据集并根据需要将跟踪信息输入请求及模型响应添加到数据集中。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/db0f7ed09c4a08f8a23720d6a454efbf.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/3f9796f949790f848308a49a81f1545c.png图 5左通过提供数据集名称和描述等必要信息直接从网页 UI 创建一个新的数据集。右可以通过点击按钮将跟踪记录添加到数据集中。来源作者类似于数据集创建和向其中添加数据点langfuse 简化了指标的创建和数据点的标注。图 6展示了只需点击几下按钮便能轻松完成相同操作。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/acf9c98a20ba18ecf4c51ad3fca07835.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/e19a439a5374973c5f72cd3a492f60ca.png图 6Langfuse 中的指标创建与标注。来源作者一旦我们准备好数据集langfuse 提供了一个简单的 SDK让你在你喜欢的编程语言中使用它。以下代码片段使用 langfuse 的 get_dataset 工具从我们添加到示例数据集中的几个跟踪记录中获取数据。然后我们仅通过一行代码修改便能用 LLaMA 3.1 来驱动我们的 DSPy RAG 程序说到模块化 。# get annotated datasetannotated_datasetlangfuse.get_dataset(llm_workshop_rag)# ensure ollama is available in your environmentollama_dspydspy.OllamaLocal(modelllama3.1,temperature0.5)# get langfuse client from the dspy tracker objectlangfuselangfuse_tracker.langfuse# Set up the ollama as LM and RMdspy.settings.configure(lmollama_dspy,rmretriever_model)# test rag using ollamaollama_ragRAG()# iterate through samples from the annotated datasetforiteminannotated_dataset.items:questionitem.input[0][content].split(Question: )[-1].split(\n)[0]answeritem.expected_output[content].split(Answer: )[-1]o_predollama_rag(question)# add observations to dataset related experimentswithitem.observe(run_nameollama_experiment,run_descriptioncompare LLaMA3.1 RAG vs GPT4o-mini RAG ,run_metadata{model:llama3.1},)astrace_id:langfuse.score(namevisual-eval,# any float valuevalue1.0,commentLLaMA3.1 is very verbose,)# attach trace with new runlangfuse.trace(inputquestion,outputo_pred.answer,metadata{model:LLaMA3.1})display(Markdown(f__Question__:{question}))display(Markdown(f__Predicted Answer (LLaMA 3.1)__:{o_pred.answer}))display(Markdown(f__Annotated Answer (GPT-4o-mini)__: _{answer}_))如上面的代码片段所示我们只需遍历数据集中的数据点直观地比较两个模型的输出参见图 7。使用 Langfuse SDK我们可以轻松地将实验观察结果、新的跟踪记录和评估分数附加上去。https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/5f7debc33c398b2935a9540b2ca759f1.pnghttps://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/24ffbca1793fbdb95aea3c357b05b398.png图 7使用 Langfuse 准备的数据集中的数据点为 LLaMA3.1 驱动的 RAG 提供输出图 7 中展示的输出清晰地显示了 LLaMA3.1 驱动的 RAG 确实能回答问题但在简洁性方面偏离了指令。这可以通过 DSPy 断言轻松捕捉到同时可以使用 langfuse SDK 跟踪分数以便进行进一步改进。结论在这个快速发展的 LLM 应用领域像 DSPy 和 Langfuse 这样的工具成为开发者和数据科学家的宝贵助手。DSPy 简化了开发过程使你能够轻松高效地构建复杂的 LLM 应用。同时Langfuse 提供了关键的可观察性层让你深入了解模型的表现优化资源利用并基于真实数据持续改进应用。DSPY 和 Langfuse 的结合解锁了无限可能让你能够充分发挥 LLM 的潜力。无论你是在构建问答系统、内容生成器还是其他任何基于 LLM 的应用这些工具都为创建强大、可扩展和富有洞察力的解决方案奠定了基础。正如我在最近的 LLM 工作坊的元使用案例——回答问题——中所展示的DSPy 和 Langfuse 可以创造性地应用于从你自己的个人数据中提取有价值的洞察。可能性真的无穷无尽。我鼓励你在自己的项目中探索这些工具/框架。感兴趣的朋友可以通过我的GitHub 仓库获取更多关于其他主题的综合性实践工作坊资料。借助这些工具你将能够大幅提升你的 LLM 应用并在快速发展的 AI 领域中保持领先。免责声明我与文中提到的任何工具、产品或公司没有任何关联不论是财务上的还是其他方面的。这些观点和见解仅基于个人经验和独立研究。参考资料DSPyLangfuse[## GitHub - raghavbali/llm_workshop: LLM Workshop 2024LLM Workshop 2024。通过在 GitHub 上创建账户参与 raghavbali/llm_workshop 项目的开发。github.com](https://github.com/raghavbali/llm_workshop.git?sourcepost_page-----f83c02ba96a1--------------------------------)