1. 项目概述一个为大型语言模型应用开发降本增效的框架如果你正在或打算基于大语言模型LLM构建应用比如一个智能客服、一个文档分析助手或者一个创意写作工具那么你大概率会遇到一个核心痛点成本。这里的成本不仅仅是调用API的金钱开销更包括为了获得稳定、可靠的输出而投入的工程开发、提示词调试、流程编排的精力与时间成本。每次模型迭代、每次需求变更都可能意味着大量的代码重构和漫长的测试周期。datawhalechina/easy-langent这个开源项目正是瞄准了这个痛点。它不是一个全新的LLM而是一个应用开发框架。你可以把它理解为一个“乐高积木箱”和“搭建说明书”的结合体。它提供了一套标准化的接口、组件和工具让你能用更少的代码更清晰地组织你的LLM应用逻辑从而把精力从繁琐的工程细节中解放出来聚焦在业务逻辑和创新本身。它的核心价值在于“易用”和“高效”。对于初学者它降低了入门门槛提供了清晰的范式对于有经验的开发者它提供了可复用的模块和最佳实践能显著提升开发效率和项目的可维护性。接下来我们就深入拆解这个框架的设计思路、核心组件以及如何用它来构建一个实实在在的应用。2. 框架核心设计思想与架构拆解2.1 为什么需要另一个LLM框架市面上已经存在不少优秀的LLM应用框架比如 LangChain、LlamaIndex 等。easy-langent的出现并非为了简单重复而是基于 Datawhale 社区在AI教育和项目实践中的观察针对一些特定场景和痛点进行的优化与整合。2.1.1 面向中文场景与社区友好许多主流框架虽然功能强大但其文档、示例和社区讨论仍以英文为主对于中文开发者尤其是在学习阶段的开发者存在一定的理解和使用门槛。easy-langent从诞生起就注重中文文档和示例其设计也更多地考虑了中文文本处理、国内主流模型平台如百度文心、阿里通义、智谱AI等的集成降低了国内开发者的接入成本。2.1.2 强调“轻量”与“清晰”一些大型框架为了追求功能的全面性架构变得比较重概念层较多学习曲线陡峭。easy-langent的设计哲学是“够用就好”和“直观清晰”。它提炼了LLM应用开发中最核心、最通用的模式用更简洁的抽象和更直接的API来实现让开发者能快速理解框架的运作方式避免在复杂的概念中迷失。2.1.3 专注于应用流程编排它将LLM视为一个强大的“处理器”而框架的核心任务是高效、可靠地组织“数据”流经这个处理器的管道Pipeline。因此它在设计上非常强调**链Chain和代理Agent**的构建与管理并提供了便捷的工具来组装、调试和监控这些流程。2.2 核心架构三层视图为了理解easy-langent我们可以将其架构分为三层基础层、组件层和应用层。基础层Foundation这一层提供了框架的基石主要包括模型抽象Model Abstraction定义了一个统一的接口来与各种LLM如 OpenAI GPT、Claude、国内大模型进行交互。无论底层模型如何变化上层的代码只需关注统一的输入输出格式。消息格式Message Schema标准化了与LLM对话的消息结构例如系统提示System Message、用户输入Human Message、助手回复AI Message等。这确保了信息在不同组件间传递的一致性。核心运行时Core Runtime管理组件的执行顺序、错误处理、异步调用等基础能力。组件层Components这是框架的“积木块”提供了可插拔的功能模块提示词模板Prompt Templates将动态变量如用户查询、上下文注入到预设的提示词中实现提示词的工程化管理。记忆Memory用于存储和检索对话历史或上下文信息使LLM具备“记忆”能力实现多轮对话。工具Tools将外部功能如计算器、搜索引擎、数据库查询、自定义函数封装成LLM可以理解和调用的“工具”极大地扩展了LLM的能力边界。检索器Retrievers与向量数据库等结合实现从外部知识库中高效检索相关信息并将其作为上下文提供给LLM即RAG检索增强生成。输出解析器Output Parsers将LLM自由格式的文本输出解析成结构化的数据如JSON、Pydantic模型方便后续程序处理。应用层Application通过组合底层的组件构建出具体的应用模式链Chain将多个LLM调用或其他处理步骤按顺序组合成一个固定的工作流。例如“检索 - 生成提示 - 调用LLM - 解析结果”就是一个典型的链。代理Agent一个更高级的抽象它让LLM具备“思考”和“决策”能力。代理可以根据目标自主决定调用哪些工具、以什么顺序调用并循环此过程直至完成任务。这是构建复杂自主应用的关键。这个分层架构的好处是解耦和灵活。你可以直接使用高层应用模式快速搭建原型也可以深入底层定制或替换任何一个组件以适应你的特殊需求。3. 关键组件深度解析与实战配置理解了架构我们来看看如何具体使用这些“积木块”。这里以几个最关键的组件为例说明其用法和配置要点。3.1 模型接入一站式管理多种LLM在easy-langent中初始化一个模型变得非常简单。它通常通过一个统一的LLM类来封装不同供应商的模型。from easy_langent.llms import OpenAIChat, WenxinChat, SparkChat # 1. 接入 OpenAI GPT openai_llm OpenAIChat( modelgpt-3.5-turbo, api_keyyour-openai-api-key, temperature0.7, # 控制创造性0-1之间越高越随机 max_tokens1024 ) # 2. 接入百度文心一言 wenxin_llm WenxinChat( modelERNIE-Bot-turbo, api_keyyour-wenxin-api-key, secret_keyyour-wenxin-secret-key, temperature0.8 ) # 3. 接入讯飞星火 spark_llm SparkChat( app_idyour-spark-app-id, api_keyyour-spark-api-key, api_secretyour-spark-api-secret, temperature0.5 )关键配置参数解析temperature这是最重要的参数之一。它控制输出的随机性。值越低如0.1输出越确定、保守适合事实问答、代码生成值越高如0.9输出越有创意、多样化适合创意写作、头脑风暴。通常从0.7开始调试。max_tokens限制模型单次回复的最大长度。需要根据你的场景和模型上下文窗口来设置设置过小可能导致回答被截断。api_key等认证信息强烈建议不要硬编码在代码中应使用环境变量或配置文件管理。# 在终端中设置环境变量 export OPENAI_API_KEYsk-...# 在代码中读取 import os api_key os.environ.get(OPENAI_API_KEY)注意不同模型平台的参数名称和取值范围可能略有不同easy-langent在内部做了适配但调用时仍需参考对应模型的官方文档。例如文心一言的temperature叫top_p但框架的接口可能统一为temperature。3.2 提示词工程从字符串模板到可管理资产直接拼接字符串来构造提示词是脆弱且难以维护的。easy-langent的PromptTemplate组件解决了这个问题。from easy_langent.prompts import PromptTemplate # 定义一个包含变量的模板 template 你是一个专业的{role}。 请根据以下背景信息回答用户的问题。 背景信息 {context} 用户问题 {question} 请用{language}回答并确保回答专业、准确。 prompt_template PromptTemplate( input_variables[role, context, question, language], templatetemplate ) # 使用模板动态填充变量 filled_prompt prompt_template.format( role机器学习工程师, context随机森林是一种集成学习算法。, question请解释随机森林的工作原理。, language中文 ) print(filled_prompt) # 然后将 filled_prompt 发送给 LLM进阶用法提示词仓库对于复杂的应用提示词可能非常多。最佳实践是将它们存储在独立的文件如JSON、YAML或数据库中进行版本管理。# prompts.yaml summarize: template: | 请用不超过{max_length}字总结以下文本 {text} input_variables: [text, max_length] translate: template: | 将以下{source_lang}文本翻译成{target_lang} {text} input_variables: [text, source_lang, target_lang]然后在代码中加载和使用import yaml with open(prompts.yaml, r) as f: prompt_registry yaml.safe_load(f) summarize_template PromptTemplate.from_template(prompt_registry[summarize][template])3.3 记忆管理实现连贯的多轮对话要让LLM记住之前的对话内容需要使用Memory组件。最简单常用的是ConversationBufferMemory。from easy_langent.memory import ConversationBufferMemory from easy_langent.llms import OpenAIChat from easy_langent.chains import ConversationChain # 初始化记忆和模型 memory ConversationBufferMemory(memory_keychat_history, return_messagesTrue) llm OpenAIChat(modelgpt-3.5-turbo, temperature0.7) # 创建一个对话链 conversation ConversationChain(llmllm, memorymemory, verboseTrue) # 进行多轮对话 response1 conversation.run(你好我叫小明。) print(fAI: {response1}) # 输出可能为AI: 你好小明很高兴认识你。 response2 conversation.run(你还记得我叫什么名字吗) print(fAI: {response2}) # 输出可能为AI: 当然记得你刚才告诉我你叫小明。ConversationBufferMemory会像一个列表一样保存所有的对话历史。memory_keychat_history指定了在提示词模板中用于插入历史记录的变量名。return_messagesTrue表示以消息对象列表的形式返回便于框架处理。记忆类型的选型ConversationBufferMemory保存所有历史简单但上下文可能过长消耗token。ConversationBufferWindowMemory只保存最近K轮对话控制上下文长度。ConversationSummaryMemory让LLM自动总结之前的对话历史然后只保存总结摘要适合超长对话。VectorStoreRetrieverMemory将历史对话存入向量数据库根据当前问题检索相关历史片段实现“长期记忆”。选择哪种记忆方式取决于你的应用对上下文长度、精度和成本的要求。3.4 工具调用赋予LLM“手”和“脚”工具Tools是LLM与外部世界交互的桥梁。easy-langent让定义和使用工具变得非常直观。from easy_langent.tools import Tool from easy_langent.agents import initialize_agent, AgentType import requests import json # 1. 定义一个获取天气的工具 def get_weather(city: str) - str: 根据城市名获取当前天气情况。 # 这里使用一个模拟的天气API # 真实场景应替换为真正的API调用并处理错误 weather_data { 北京: 晴25°C, 上海: 多云28°C, 广州: 雷阵雨30°C } return weather_data.get(city, f未找到{city}的天气信息。) # 2. 使用 Tool 类进行包装 weather_tool Tool( nameget_weather, funcget_weather, description当用户询问某个城市的天气时使用此工具。输入应为一个城市名称字符串。 ) # 3. 定义一个计算器工具使用Lambda表达式 calculator_tool Tool( namecalculator, funclambda x: str(eval(x)), # 注意生产环境请勿使用eval此处仅为示例 description用于执行数学计算。输入应为一个数学表达式字符串如 2 3 * 4。 ) # 4. 初始化一个具备工具的代理Agent llm OpenAIChat(temperature0) tools [weather_tool, calculator_tool] agent initialize_agent( toolstools, llmllm, agentAgentType.ZERO_SHOT_REACT_DESCRIPTION, # 一种通用的代理类型 verboseTrue # 打印代理的思考过程便于调试 ) # 5. 运行代理 result agent.run(北京现在的天气怎么样另外123乘以456等于多少) print(result)当运行上述代码时verboseTrue会让我们看到代理的思考过程 进入新的代理链... 思考用户问了两个问题一个是天气一个是计算。我需要使用工具。 行动get_weather 行动输入北京 观察晴25°C 思考我得到了北京的天气。现在需要计算123*456。 行动calculator 行动输入123 * 456 观察56088 思考我得到了两个答案可以回复用户了。 最终答案北京现在的天气是晴25°C。123乘以456等于56088。工具定义的核心要点清晰的描述description这是LLM决定是否以及如何调用工具的关键。描述必须准确说明工具的功能和输入格式。明确的输入输出工具函数应有清晰的参数和返回类型。框架会利用这些信息来帮助LLM理解。错误处理在真实的工具函数内部务必包含健壮的错误处理try-catch并返回友好的错误信息避免整个代理链因工具调用失败而崩溃。工具的选择不要给代理提供过多或不必要的工具这会导致LLM困惑。根据任务精准提供工具集。4. 构建完整应用从链到代理的实战现在我们将上述组件组合起来构建两个典型的应用一个基于链的文档摘要工具和一个基于代理的智能助手。4.1 实战一构建一个可检索上下文的文档问答链RAG Pipeline这个应用模拟一个企业知识库问答系统。用户提问系统先从向量库中查找相关文档片段然后结合这些片段让LLM生成答案。步骤1准备知识库并创建向量索引假设我们有一系列Markdown格式的文档。from langent_community.document_loaders import TextLoader from langent_community.text_splitter import RecursiveCharacterTextSplitter from langent_community.embeddings import OpenAIEmbeddings from langent_community.vectorstores import Chroma import os # 1. 加载文档 documents [] for file in os.listdir(./knowledge_base): if file.endswith(.md): loader TextLoader(f./knowledge_base/{file}, encodingutf-8) documents.extend(loader.load()) # 2. 分割文本因为LLM上下文长度有限 text_splitter RecursiveCharacterTextSplitter( chunk_size500, # 每个片段约500字符 chunk_overlap50 # 片段间重叠50字符保持语义连贯 ) split_docs text_splitter.split_documents(documents) # 3. 创建嵌入模型和向量数据库 embeddings OpenAIEmbeddings() # 需要OPENAI_API_KEY vectorstore Chroma.from_documents( documentssplit_docs, embeddingembeddings, persist_directory./chroma_db # 持久化存储 ) # 现在 vectorstore 就是一个检索器Retriever retriever vectorstore.as_retriever(search_kwargs{k: 3}) # 检索最相关的3个片段步骤2构建提示词模板和问答链from easy_langent.prompts import PromptTemplate from easy_langent.chains import RetrievalQA # 定义提示词模板将检索到的上下文和问题结合起来 qa_template 请根据以下提供的上下文信息来回答问题。如果上下文信息不足以回答问题请直接说“根据已知信息无法回答此问题”不要编造答案。 上下文信息 {context} 问题{question} 请给出专业、准确的回答 QA_PROMPT PromptTemplate( templateqa_template, input_variables[context, question] ) # 创建检索问答链 qa_chain RetrievalQA.from_chain_type( llmOpenAIChat(modelgpt-3.5-turbo, temperature0), chain_typestuff, # 将检索到的所有上下文“塞”进提示词 retrieverretriever, chain_type_kwargs{prompt: QA_PROMPT}, return_source_documentsTrue # 返回来源文档便于溯源 ) # 使用链进行问答 result qa_chain(我们公司的年假政策是怎样的) print(f答案{result[result]}) print(来源文档) for doc in result[source_documents][:2]: # 打印前两个来源 print(f- {doc.page_content[:100]}...)关键点与避坑指南文本分割策略chunk_size和chunk_overlap需要根据文档特点和模型上下文窗口调整。技术文档可能适合较小的块300-500而叙述性文档可能需要更大的块1000。嵌入模型选择嵌入模型的质量直接决定检索效果。除了OpenAI可以考虑text-embedding-ada-002或者开源的BGE、M3E等模型easy-langent通常也支持集成。检索数量k值search_kwargs{k: 3}中的k值需要权衡。太小可能遗漏关键信息太大会增加提示词长度和成本。通常从3-5开始尝试。“无法回答”的处理提示词模板中明确要求模型在上下文不足时说“无法回答”这是构建可靠RAG系统的关键能有效减少模型“幻觉”胡编乱造。4.2 实战二构建一个多功能自主代理Agent代理能处理更开放、多步骤的任务。我们构建一个能查天气、查资料通过联网搜索、做计算的个人助理。步骤1定义更丰富的工具集from easy_langent.tools import Tool, DuckDuckGoSearchRun from easy_langent.utilities import SerpAPIWrapper import datetime # 工具1搜索使用DuckDuckGo无需API Key search DuckDuckGoSearchRun() search_tool Tool( nameweb_search, funcsearch.run, description当需要获取最新的、实时的信息如新闻、事件、未知概念时使用此工具。输入是一个搜索查询字符串。 ) # 工具2天气沿用之前的函数 weather_tool Tool( nameget_weather, funcget_weather, # 假设get_weather函数已定义 description查询指定城市的当前天气。输入是城市名。 ) # 工具3时间 def get_current_time(placeholder: str) - str: 获取当前日期和时间。输入参数无实际用处仅为满足工具格式。 now datetime.datetime.now() return now.strftime(%Y-%m-%d %H:%M:%S) time_tool Tool( nameget_time, funcget_current_time, description当被问到当前时间、今天日期时使用此工具。输入可以忽略。 ) # 工具4计算器 calculator_tool Tool(...) # 同上文定义 tools [search_tool, weather_tool, time_tool, calculator_tool]步骤2初始化并运行代理from easy_langent.agents import initialize_agent, AgentType from easy_langent.llms import OpenAIChat llm OpenAIChat(modelgpt-4, temperature0.2) # 复杂任务建议使用更强的模型如GPT-4 agent initialize_agent( toolstools, llmllm, agentAgentType.ZERO_SHOT_REACT_DESCRIPTION, verboseTrue, handle_parsing_errorsTrue, # 处理LLM输出格式错误非常重要 max_iterations5 # 限制代理的最大思考/行动步数防止死循环 ) # 执行一个复杂任务 try: result agent.run( 帮我查一下今天北京和上海的天气然后告诉我现在是什么时间最后计算一下从今天到年底还有多少天 ) print(f\n最终结果\n{result}) except Exception as e: print(f代理执行出错{e})代理开发的核心经验模型选择代理需要模型具备较强的推理和规划能力。对于简单任务gpt-3.5-turbo可能够用对于复杂、多步骤任务gpt-4或claude-3系列的成功率会高很多尽管成本也更高。处理解析错误handle_parsing_errorsTrue这个参数至关重要。LLM的输出可能偶尔不符合工具调用的格式要求这个参数能让代理尝试修复或继续而不是直接崩溃。你可以将其设置为一个自定义的错误处理函数。限制迭代次数max_iterations必须设置。代理可能会陷入“思考-行动”的循环这个参数是安全阀。清晰的工具描述再次强调工具描述是代理的“说明书”。模糊的描述会导致代理错误地调用或不调用工具。花时间打磨每个工具的description。Verbose模式调试开发阶段务必开启verboseTrue它能完整打印代理的“思考Thought”、“行动Action”、“观察Observation”链是排查问题不可或缺的手段。5. 性能优化、部署与监控当一个原型开发完成后要将其变为稳定可用的服务还需要考虑性能、成本和可观测性。5.1 成本控制与缓存策略LLM API调用是按Token计费的频繁调用相同或相似的内容会造成浪费。引入缓存是降低成本最直接有效的方法。from easy_langent.cache import InMemoryCache, SQLiteCache from easy_langent.llms import OpenAIChat # 使用内存缓存适合短期、单进程 llm_with_cache OpenAIChat( modelgpt-3.5-turbo, cacheInMemoryCache() # 相同的提示词和参数第二次调用直接返回缓存结果 ) # 使用SQLite缓存可持久化跨进程 import sqlite3 conn sqlite3.connect(./llm_cache.db) llm_with_persistent_cache OpenAIChat( modelgpt-3.5-turbo, cacheSQLiteCache(database_connectionconn) ) # 在链或代理中使用带缓存的LLM from easy_langent.chains import LLMChain prompt PromptTemplate(...) chain LLMChain(llmllm_with_persistent_cache, promptprompt) # 多次运行相同输入只有第一次会真正调用API缓存的关键考量缓存键Cache Key通常由模型名、提示词文本、温度等参数共同哈希生成。这意味着即使提示词意思相同但措辞微调也不会命中缓存。缓存失效对于实时性要求高的信息如天气、股价需要谨慎使用缓存或设置较短的TTL生存时间。分布式缓存在生产环境中多实例服务可能需要共享缓存可以考虑使用RedisCache等后端。5.2 异步处理提升吞吐量对于需要同时处理多个用户请求或批量处理大量任务的场景同步调用LLM会导致请求排队延迟增高。easy-langent支持异步操作。import asyncio from easy_langent.llms import OpenAIChat async def process_batch_queries(queries): llm OpenAIChat() tasks [] for query in queries: # 创建异步任务而不是立即执行 task llm.apredict(query) # 注意是 apredict 而不是 predict tasks.append(task) # 并发执行所有任务 results await asyncio.gather(*tasks, return_exceptionsTrue) # 处理结果 for query, result in zip(queries, results): if isinstance(result, Exception): print(f处理 {query} 时出错{result}) else: print(fQ: {query}\nA: {result}\n) # 运行异步函数 queries [什么是机器学习, Python的优点是什么, 解释一下神经网络。] asyncio.run(process_batch_queries(queries))异步使用注意事项API速率限制即使你使用了异步也要注意LLM服务商如OpenAI的每分钟请求数RPM和每分钟Token数TPM限制。需要在代码中实现限流例如使用asyncio.Semaphore。错误处理并发环境下的错误处理更重要。return_exceptionsTrue可以防止一个任务失败导致整个gather失败。上下文管理确保异步操作中使用的资源如数据库连接、HTTP会话是线程安全或支持异步的。5.3 日志记录与监控生产系统必须要有完善的日志和监控以便追踪问题、分析用量和性能。import logging from easy_langent.callbacks import BaseCallbackHandler # 1. 配置基础日志 logging.basicConfig( levellogging.INFO, format%(asctime)s - %(name)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(llm_app.log), logging.StreamHandler() ] ) logger logging.getLogger(__name__) # 2. 自定义回调处理器捕获LLM生命周期事件 class MonitoringCallback(BaseCallbackHandler): def on_llm_start(self, serialized, prompts, **kwargs): logger.info(fLLM调用开始提示词: {prompts[:100]}...) # 记录前100字符 self.start_time time.time() def on_llm_end(self, response, **kwargs): duration time.time() - self.start_time token_usage response.llm_output.get(token_usage, {}) if hasattr(response, llm_output) else {} logger.info(fLLM调用结束耗时: {duration:.2f}s, Token使用: {token_usage}) def on_tool_start(self, serialized, input_str, **kwargs): logger.info(f工具调用开始: {serialized.get(name)}, 输入: {input_str}) def on_tool_end(self, output, **kwargs): logger.info(f工具调用结束输出: {output[:200]}...) # 记录前200字符 # 3. 在链或代理中使用回调 callbacks [MonitoringCallback()] agent initialize_agent( toolstools, llmllm, agentAgentType.ZERO_SHOT_REACT_DESCRIPTION, callbackscallbacks, # 传入回调处理器 verboseFalse # 可以关闭框架自带的verbose用我们自己的日志 ) # 4. 记录业务逻辑 try: result agent.run(用户问题) logger.info(f代理运行成功结果: {result}) except Exception as e: logger.error(f代理运行失败: {e}, exc_infoTrue) # exc_info记录堆栈跟踪监控维度建议性能每次LLM调用、工具调用的延迟P95 P99。成本记录每次调用的输入/输出Token数按模型折算成本。质量对于问答类应用可以抽样进行人工评估或设计自动化指标如答案与标准答案的相似度。错误率跟踪各类错误API错误、解析错误、超时的发生频率。可视化将日志导入到GrafanaLoki或ELK栈中制作监控大盘。6. 常见问题排查与进阶技巧在实际开发和运维中你肯定会遇到各种问题。这里总结一些典型场景和解决思路。6.1 问题排查清单问题现象可能原因排查步骤与解决方案LLM返回无关或质量差的答案1. 提示词不清晰或指令不强。2. 温度temperature参数过高。3. 提供的上下文不足或噪声大。1.优化提示词使用更明确的指令如“请严格按照以下格式回答”。在提示词开头强调角色和任务。2.降低temperature尝试设置为0.1-0.3使输出更确定。3.检查检索质量对于RAG查看检索到的文档是否相关。调整检索器的k值或优化嵌入模型/文本分割策略。代理陷入循环或调用错误工具1. 工具描述不准确。2. 模型推理能力不足。3. 任务过于复杂或模糊。1.精炼工具描述确保描述清晰说明工具用途、输入格式和适用场景。2.升级模型尝试使用gpt-4等更强模型。3.简化任务或提供示例将大任务拆解或在提示词中给代理提供一两个思考示例Few-shot。4.设置max_iterations防止无限循环。API调用超时或速率限制1. 网络问题或服务端不稳定。2. 请求频率超过供应商限制。3. 响应内容过长。1.增加超时时间在LLM初始化时设置request_timeout参数。2.实现重试与退避使用tenacity等库为API调用添加指数退避重试机制。3.实施客户端限流控制并发请求数尤其是在异步场景下。4.检查max_tokens确保设置合理不会因生成过长而超时。解析LLM输出时出错1. LLM输出不符合预期格式如JSON解析失败。2. 输出解析器Output Parser定义有误。1.开启handle_parsing_errors在代理初始化时设置此参数为True或一个处理函数。2.使用更严格的提示词要求LLM“必须输出JSON格式且只包含如下字段...”。3.采用Pydantic模型解析easy-langent支持用Pydantic模型定义期望结构解析更健壮。记忆Memory不工作1. 记忆对象未正确传递给链。2. 提示词模板中未包含记忆变量。3. 记忆类型选择不当导致信息丢失。1.检查链的初始化确认memorymemory参数已传入。2.检查提示词确认模板中包含{chat_history}或你定义的memory_key对应的变量。3.切换记忆类型对于长对话尝试ConversationSummaryMemory或ConversationBufferWindowMemory。6.2 进阶技巧与最佳实践提示词版本化与管理将提示词存储在代码库之外如数据库、配置中心并附带版本号。这样可以在不重新部署代码的情况下进行A/B测试和快速回滚。实现“Fallback”策略对于关键应用不要只依赖一个LLM供应商或一个模型。可以设置一个主模型和一个备胎模型。当主模型调用失败或返回质量过低时自动切换到备胎。from easy_langent.llms import OpenAIChat, WenxinChat from easy_langent.output_parsers import RetryWithErrorOutputParser primary_llm OpenAIChat(modelgpt-4) fallback_llm WenxinChat(modelERNIE-Bot-4) # 简化示例在实际中可能需要更复杂的逻辑判断 try: response primary_llm.predict(prompt) if is_low_quality(response): # 自定义的质量检查函数 raise ValueError(Primary LLM response quality low) except Exception as e: logger.warning(fPrimary LLM failed: {e}, switching to fallback.) response fallback_llm.predict(prompt)对输出进行后处理与验证不要完全信任LLM的输出。特别是涉及事实、数据或格式时应添加后处理层进行清洗、验证或格式化。例如让LLM输出一个包含“答案”和“置信度”字段的JSON然后根据置信度决定是否采纳或触发人工审核。评估与持续改进建立评估流水线。准备一批测试用例黄金数据集定期用你的应用跑一遍评估答案的准确性、相关性和有用性。这能帮你量化每次提示词或流程修改的效果。easy-langent作为一个框架提供了构建LLM应用所需的脚手架和最佳实践集成。它的真正价值在于让你能更快速、更规范地启动项目并将更多精力投入到解决具体的业务问题和优化用户体验上。从简单的链开始逐步过渡到复杂的代理结合缓存、异步、监控等工程化手段你就能构建出既智能又稳健的生产级应用。