尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

从Prompt到Agent:基于LangChain与RAG的AI应用开发实战指南

从Prompt到Agent:基于LangChain与RAG的AI应用开发实战指南 大家好我是专注于AI应用开发的技术博主。随着大模型技术的飞速发展如何高效地构建智能应用已成为开发者必须掌握的技能。你是否曾面对海量的LangChain、RAG、Agent等概念感到无从下手是否在尝试构建一个简单的AI助手时被复杂的工具链和晦涩的文档劝退本文将为你系统梳理从Prompt工程到Agent应用开发的完整知识体系结合LangChain、RAG、MCP等核心框架手把手带你从零搭建可运行的AI应用并深入探讨大模型微调的实战方法。无论你是希望入门AI应用开发的新手还是寻求项目落地的进阶开发者都能从这篇万字长文中找到清晰的路径和可复现的代码。1. 背景与核心概念为什么需要AI应用开发框架在ChatGPT等大模型出现之前构建一个智能对话系统需要大量的领域数据、复杂的NLP模型训练和繁琐的工程集成。如今大语言模型LLM提供了强大的通用能力但直接调用API往往无法满足复杂的业务需求。我们需要一套“胶水”和“脚手架”将大模型的能力与外部工具、私有数据、业务流程无缝连接起来。这就是AI应用开发框架的价值所在。1.1 核心概念解析Prompt提示词这是与大模型交互的“指令”或“问题”。Prompt的质量直接决定了模型输出的效果。它不仅仅是简单的提问更包含了上下文、角色设定、输出格式要求、示例Few-shot等复杂结构。编写优秀的Prompt是一门工程艺术。LangChain一个用于开发由语言模型驱动的应用程序的框架。它的核心思想是“链”Chain通过将多个组件如模型调用、提示模板、记忆、工具等链接起来构建复杂的应用工作流。它抽象了与大模型交互的复杂性提供了模块化的组件。RAG检索增强生成解决大模型“幻觉”生成虚假信息和知识截止问题的关键技术。其原理是当用户提问时先从外部知识库如向量数据库中检索出相关的文档片段然后将这些片段作为上下文与问题一起提交给大模型让模型基于提供的可靠信息生成答案。这极大地提升了答案的准确性和可信度。Agent智能体一个能感知环境、进行决策并执行动作以完成目标的系统。在LLM语境下Agent通常指一个由大模型驱动的“大脑”它可以调用各种工具如计算器、搜索引擎、数据库API来完成任务。LangChain提供了构建Agent的核心组件。MCPModel Context Protocol模型上下文协议一个由Anthropic提出的开放协议旨在标准化LLM与外部工具、数据源之间的连接方式。它使得不同的AI应用和工具能更容易地集成和互操作是构建复杂AI生态系统的底层基础设施之一。大模型微调针对特定领域或任务使用额外的数据集对预训练好的大模型进行继续训练使其在该领域表现更专业。与Prompt Engineering提示工程相比微调能更深度地改变模型的行为但成本也更高。1.2 它们之间的关系你可以这样理解Prompt是与模型沟通的语言。LangChain是用这种语言构建复杂对话和流程的工厂。RAG是给这个工厂接入了一个庞大的资料库确保它说的话有据可依。Agent是让这个工厂拥有了手和脚可以主动操作工具去完成任务。MCP是为工厂和外部工具之间制定了标准的接线规范。而微调则是直接培训工厂里的核心工人模型让他更擅长某一类工作。2. 环境准备与版本说明在开始实战之前我们需要搭建一个稳定、可复现的开发环境。本文将使用Python作为主要开发语言。2.1 基础环境操作系统Windows 10/11, macOS, 或 Linux (Ubuntu 20.04)。本文示例在 macOS/Linux 环境下编写Windows 用户请注意路径差异。Python版本Python 3.8 - 3.11。强烈建议使用3.10或3.11以获得最佳兼容性。LangChain等库对Python 3.12的支持可能仍在完善中。包管理工具pip(建议版本21.3)。推荐使用虚拟环境venv或conda隔离项目依赖。2.2 核心依赖库及版本创建一个新的项目目录并初始化一个requirements.txt文件。以下是本文涉及的核心库及推荐版本版本会持续更新请以实际为准# requirements.txt # 核心框架 langchain0.1.0 langchain-community0.0.10 # 社区贡献的集成工具 langchain-core0.1.0 # 大模型接口 (以OpenAI为例也可替换为其他) openai1.3.0 # 向量数据库与嵌入模型 (以Chroma和OpenAI Embeddings为例) chromadb0.4.22 langchain-openai0.0.5 # LangChain对OpenAI的官方集成 tiktoken0.5.1 # 用于Token计数 # 用于网页内容加载 beautifulsoup44.12.2 langchain-community[web-base] # 包含常用文档加载器 # 实用工具 python-dotenv1.0.0 # 管理环境变量 jupyter1.0.0 # 可选用于交互式实验2.3 环境变量与API密钥大模型服务通常需要API Key。为了安全绝不将密钥硬编码在代码中。我们使用.env文件管理。在项目根目录创建.env文件。填入你的API密钥以OpenAI为例# .env OPENAI_API_KEYsk-your-actual-openai-api-key-here在代码中通过python-dotenv加载# config.py 或主程序开头 from dotenv import load_dotenv import os load_dotenv() # 加载 .env 文件中的变量到环境变量 openai_api_key os.getenv(OPENAI_API_KEY) if not openai_api_key: raise ValueError(请在 .env 文件中设置 OPENAI_API_KEY)3. 核心语法、配置与原理拆解3.1 Prompt Engineering从简单到复杂Prompt是与模型沟通的起点。一个糟糕的Prompt会导致无用的输出。3.1.1 基础Promptfrom langchain_openai import ChatOpenAI llm ChatOpenAI(modelgpt-3.5-turbo, api_keyos.getenv(OPENAI_API_KEY)) # 简单提问 response llm.invoke(法国的首都是哪里) print(response.content) # 输出巴黎3.1.2 使用提示模板PromptTemplate模板允许我们动态插入变量构建复杂的提示。from langchain.prompts import ChatPromptTemplate template ChatPromptTemplate.from_messages([ (system, 你是一位专业的{domain}专家回答要简洁准确。), (human, 请解释一下{concept}。) ]) # 填充模板 prompt template.invoke({domain: 机器学习, concept: 过拟合}) print(prompt.to_string()) # 输出 # System: 你是一位专业的机器学习专家回答要简洁准确。 # Human: 请解释一下过拟合。 # 将模板与模型连接成链Chain chain template | llm # LangChain 0.1.x 推荐使用管道运算符 response chain.invoke({domain: 机器学习, concept: 过拟合}) print(response.content)3.1.3 少样本提示Few-shot Prompting提供几个输入-输出的例子引导模型学会特定格式或风格。from langchain.prompts import FewShotChatMessagePromptTemplate, ChatPromptTemplate examples [ {input: 22, output: 4}, {input: 5*3, output: 15}, ] example_prompt ChatPromptTemplate.from_messages([ (human, {input}), (ai, {output}), ]) few_shot_prompt FewShotChatMessagePromptTemplate( examplesexamples, example_promptexample_prompt, ) final_prompt ChatPromptTemplate.from_messages([ (system, 你是一个计算器只输出数字结果。), few_shot_prompt, (human, {user_input}), ]) chain final_prompt | llm response chain.invoke({user_input: 10/2}) print(response.content) # 输出53.2 LangChain核心链Chains、记忆Memory与代理Agents3.2.1 链Chains链是将多个组件顺序执行的核心抽象。除了上面使用的管道运算符还有更复杂的LCELLangChain Expression Language来构建链。from langchain.schema import StrOutputParser # 一个简单的链模板 - 模型 - 输出解析器 prompt ChatPromptTemplate.from_template(用一句话介绍{product}。) chain prompt | llm | StrOutputParser() # StrOutputParser将模型输出解析为字符串 result chain.invoke({product: Python编程语言}) print(result)3.2.2 记忆Memory为了让模型在对话中记住上下文需要使用记忆组件。from langchain.memory import ConversationBufferMemory from langchain.chains import ConversationChain memory ConversationBufferMemory(return_messagesTrue) # 存储对话历史 conversation ConversationChain(llmllm, memorymemory, verboseTrue) # verboseTrue 打印详细过程 print(conversation.invoke({input: 你好我叫小明})) print(conversation.invoke({input: 我的名字是什么})) # 模型会回答“你叫小明”3.2.3 代理Agents与工具Tools代理是能使用工具的链。首先需要定义工具。from langchain.agents import create_react_agent, AgentExecutor from langchain.tools import Tool from langchain import hub # 从Hub拉取预设的提示 # 1. 定义一个简单的工具计算字符串长度 def get_string_length(input_str: str) - str: 计算输入字符串的长度。 return f字符串 {input_str} 的长度是 {len(input_str)}。 length_tool Tool( nameString Length Calculator, funcget_string_length, description当需要计算一个字符串的长度时使用此工具。输入一个字符串。 ) # 2. 从LangChain Hub拉取一个适合ReAct框架的提示 prompt hub.pull(hwchase17/react-chat) # 3. 创建代理 agent create_react_agent(llm, tools[length_tool], promptprompt) agent_executor AgentExecutor(agentagent, tools[length_tool], verboseTrue, handle_parsing_errorsTrue) # 4. 运行代理 result agent_executor.invoke({input: ‘Hello World’ 这个字符串有多长}) print(result[output])运行上述代码你会看到代理的思考过程因为verboseTrue它决定调用String Length Calculator工具得到结果后再组织语言回答用户。3.3 RAG核心流程文档加载、切分、向量化与检索RAG的流程可以概括为索引Indexing和检索生成Retrieval Generation。3.3.1 索引流程加载文档从PDF、网页、数据库等来源加载文本。文本分割将长文档切分成适合模型上下文窗口的小块Chunks。生成向量嵌入使用嵌入模型如text-embedding-ada-002将文本块转换为数值向量。存储向量将向量和对应的文本元数据存入向量数据库。3.3.2 检索生成流程用户提问。问题向量化将用户问题转换为向量。语义检索在向量数据库中查找与问题向量最相似的文本块。构造增强提示将检索到的文本块作为上下文与原始问题一起构造最终的Prompt。生成答案大模型基于增强后的Prompt生成最终答案。4. 完整实战案例构建一个本地知识库问答系统我们将构建一个基于RAG的问答系统它可以回答关于特定文档集例如你的公司内部文档或技术手册的问题。4.1 创建项目结构my_rag_project/ ├── .env # 存储API密钥 ├── requirements.txt # 项目依赖 ├── data/ # 存放原始文档 │ └── my_document.txt ├── chroma_db/ # 向量数据库持久化目录自动创建 ├── index.py # 文档索引脚本 └── query.py # 问答查询脚本4.2 安装依赖并准备文档在项目根目录下执行pip install -r requirements.txt在data/my_document.txt中放入一些文本内容例如一段关于LangChain的介绍。4.3 编写索引脚本index.py这个脚本负责读取文档、处理并存入向量数据库。# index.py import os from dotenv import load_dotenv from langchain_community.document_loaders import TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import Chroma # 加载环境变量 load_dotenv() # 1. 加载文档 loader TextLoader(./data/my_document.txt, encodingutf-8) documents loader.load() print(f加载了 {len(documents)} 个文档) # 2. 分割文本 text_splitter RecursiveCharacterTextSplitter( chunk_size500, # 每个块的最大字符数 chunk_overlap50, # 块之间的重叠字符数保持上下文连贯 separators[\n\n, \n, 。, , , , 、, , ] # 中文友好的分隔符 ) chunks text_splitter.split_documents(documents) print(f将文档切分为 {len(chunks)} 个文本块) # 3. 初始化嵌入模型和向量数据库 embeddings OpenAIEmbeddings(modeltext-embedding-ada-002) # persist_directory 指定向量数据库的持久化路径 vectorstore Chroma.from_documents( documentschunks, embeddingembeddings, persist_directory./chroma_db # 数据将保存在此目录 ) print(文档已成功索引并存入向量数据库。)运行python index.py完成索引构建。4.4 编写查询脚本query.py这个脚本实现检索增强生成RAG的问答功能。# query.py import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI, OpenAIEmbeddings from langchain_community.vectorstores import Chroma from langchain.chains import create_retrieval_chain from langchain.chains.combine_documents import create_stuff_documents_chain from langchain.prompts import ChatPromptTemplate load_dotenv() # 1. 加载已存在的向量数据库 embeddings OpenAIEmbeddings(modeltext-embedding-ada-002) vectorstore Chroma( persist_directory./chroma_db, embedding_functionembeddings ) # 将向量数据库转换为检索器Retriever retriever vectorstore.as_retriever(search_kwargs{k: 3}) # 检索最相关的3个块 # 2. 定义LLM llm ChatOpenAI(modelgpt-3.5-turbo) # 3. 定义提示模板 system_prompt ( 你是一个专业的助手请严格根据提供的上下文来回答问题。 如果上下文中的信息不足以回答问题请直接说‘根据提供的资料我无法回答这个问题’。 不要编造信息。\n\n 上下文\n{context} ) prompt ChatPromptTemplate.from_messages([ (system, system_prompt), (human, {input}), ]) # 4. 创建文档组合链和检索链 combine_docs_chain create_stuff_documents_chain(llm, prompt) rag_chain create_retrieval_chain(retriever, combine_docs_chain) # 5. 提问 while True: user_input input(\n请输入你的问题输入‘退出’或‘quit’结束: ) if user_input.lower() in [退出, quit]: break if not user_input.strip(): continue response rag_chain.invoke({input: user_input}) print(f\n答案{response[answer]}) # 可选查看检索到的来源 # print(\n参考来源) # for i, doc in enumerate(response[context]): # print(f[{i1}] {doc.page_content[:200]}...)运行python query.py输入关于你文档内容的问题系统会从索引中检索相关信息并生成答案。4.5 进阶集成对话记忆让RAG系统记住之前的对话。# query_with_memory.py from langchain.memory import ConversationBufferMemory from langchain.chains import ConversationalRetrievalChain memory ConversationBufferMemory(memory_keychat_history, return_messagesTrue) qa_chain ConversationalRetrievalChain.from_llm( llmllm, retrieverretriever, memorymemory, verboseTrue # 查看内部过程 ) response qa_chain.invoke({question: LangChain是什么}) print(response[answer]) response qa_chain.invoke({question: 它主要解决什么问题}) # 这个问题会基于之前的对话历史 print(response[answer])5. 常见问题与排查思路在开发过程中你可能会遇到以下问题问题现象常见原因解决思路ModuleNotFoundError: No module named ‘langchain’依赖未安装或虚拟环境未激活。1. 确认已激活虚拟环境。2. 运行pip install -r requirements.txt。openai.error.AuthenticationErrorAPI密钥错误或未设置。1. 检查.env文件中的OPENAI_API_KEY是否正确。2. 确认代码中已调用load_dotenv()。3. 检查OpenAI账户余额或权限。InvalidRequestError: This model’s maximum context length is ...输入文本Prompt上下文超过模型令牌限制。1. 减小chunk_size。2. 使用RecursiveCharacterTextSplitter更精细地分割文档。3. 选择上下文窗口更大的模型如gpt-3.5-turbo-16k,gpt-4。RAG回答“根据资料无法回答”或答案不相关检索到的文本块与问题不匹配。1. 调整检索器参数search_kwargs{“k”: 5}增加检索数量。2. 尝试不同的embedding模型。3. 优化文本分割策略chunk_size和chunk_overlap。4. 检查原始文档质量。Agent陷入循环或调用错误工具提示Prompt对工具的指令不清晰或工具描述不准确。1. 优化Agent的提示词明确任务步骤和工具使用条件。2. 为工具编写更精确的description。3. 设置max_iterations限制代理的最大思考步骤。向量数据库检索速度慢向量索引未优化或数据量过大。1. 对于Chroma确保使用持久化模式避免每次重建。2. 考虑使用更高效的向量数据库如Pinecone, Weaviate用于生产环境。3. 对检索结果进行缓存。invalid prompt: your prompt was flagged...Prompt内容被AI服务商的安全策略拦截。1.这是内容安全策略请严格遵守。修改Prompt避免任何可能涉及暴力、仇恨、违法等内容。2. 将用户输入进行清洗和过滤。3. 遵循平台的使用政策。6. 最佳实践与工程建议将原型转化为可维护、可扩展的生产级应用需要注意以下方面6.1 项目结构与配置管理分离配置将模型类型、API地址、温度参数等配置项集中到config.yaml或settings.py中便于不同环境开发/测试/生产切换。模块化设计将索引逻辑、查询逻辑、工具定义、Prompt模板分别放在不同的模块中如indexing/,chains/,tools/,prompts/提高代码可读性和复用性。依赖注入避免在函数内部硬编码初始化LLM或向量数据库。通过参数传递或使用工厂模式便于单元测试和替换实现。6.2 Prompt工程优化系统提示System Prompt是灵魂明确设定AI的角色、职责和回答边界。例如“你是一个只回答编程问题的助手对其他问题一律拒绝。”结构化输出要求模型以JSON、XML或特定Markdown格式输出便于后续程序化处理。例如“请以JSON格式输出包含‘summary’和‘keywords’两个字段。”迭代优化将Prompt版本化使用A/B测试或评估框架如RAGAS、TruLens来衡量不同Prompt的效果。6.3 RAG系统优化分块策略没有银弹。对于代码可以按函数/类分割对于法律文档按条款分割。可以尝试混合不同大小的块进行检索多向量检索。元数据过滤在存入向量数据库时为每个块添加元数据如来源文件、章节、创建日期。检索时可以结合语义搜索和元数据过滤提高精度。重排序Re-ranking初步检索出N个相关文档后使用一个更小、更快的重排序模型对结果进行精排将最相关的放在前面能显著提升最终答案质量。检索后处理对检索到的多个文档块进行去重、摘要或关键信息提取再喂给LLM可以减少令牌消耗并提升信息密度。6.4 Agent开发建议工具设计工具函数应单一职责输入输出类型明确。工具描述description必须清晰无歧义这是Agent选择工具的主要依据。超时与重试为工具调用和模型调用设置超时和重试机制增强系统鲁棒性。可观测性记录Agent的完整思考过程ReAct步骤、工具调用记录和结果这对于调试复杂任务和优化Prompt至关重要。6.5 大模型微调考量何时需要微调当Prompt Engineering和RAG无法满足以下需求时1) 需要改变模型风格或语气2) 需要模型掌握非常小众、未在预训练数据中的知识3) 需要复杂、稳定的结构化输出。成本评估全参数微调成本高昂。优先考虑参数高效微调PEFT技术如LoRALow-Rank Adaptation它只训练少量参数效果接近全参数微调但成本大幅降低。数据准备微调数据质量决定上限。需要精心构造高质量的指令-回答对对于指令微调或对话数据对于对话微调。6.6 安全与合规输入输出过滤对用户输入和模型输出进行必要的敏感词过滤和内容安全检查防止生成有害内容。权限控制在Agent系统中严格限制工具可访问的数据和操作范围遵循最小权限原则。数据隐私使用RAG时确保你的私有数据在向量化和存储过程中是加密的并且API调用符合相关数据法规。7. 总结与学习路线本文带你系统性地走完了AI应用开发的核心路径从最基础的Prompt编写到利用LangChain框架构建链和记忆再到集成外部知识源的RAG系统最后到能自主使用工具的Agent。我们还探讨了更底层的MCP协议和更深度的模型微调技术。你的学习路线可以这样规划第一阶段掌握基础深入理解Prompt工程熟练使用LangChain的核心模块Models, Prompts, Chains, Memory。完成本文的RAG问答系统实战。第二阶段深入进阶探索更复杂的Agent模式Plan-and-Execute, ReAct集成更多样化的工具网络搜索、数据库、API。学习使用LangSmith进行链路追踪和调试。第三阶段优化与生产深入研究RAG的优化技巧重排序、HyDE、句子窗口检索等。将应用封装为API服务使用FastAPI并加入日志、监控和缓存。第四阶段拓展边界根据需求学习大模型微调特别是LoRA等PEFT方法或探索多模态Agent、AutoGen等多智能体框架。AI应用开发领域日新月异但核心思想是相通的理解问题、拆解模块、合理组合、持续迭代。最好的学习方式就是动手实践从一个具体的小项目开始逐步增加复杂度。希望这篇教程能成为你探索AI应用世界的坚实起点如果在实践中遇到任何问题欢迎在社区交流探讨。
返回列表