尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

大模型应用开发实战:RAG、LangChain与Agent工具调用全解析

大模型应用开发实战:RAG、LangChain与Agent工具调用全解析 “怎么让大模型回答我自己的资料”“Agent 到底怎么调用工具”“RAG、LangChain、Embedding、向量数据库这些词一次出现我该按什么顺序学”这篇就是围绕这些问题写的。标题里那一串名词——Agent 智能体、LangChain、RAG 检索增强、提示词工程、向量数据库、Embedding、工具调用——不是七门独立的课而是一条完整的大模型应用项目链路。文章会把这条链路拆开按“先跑通、再优化、最后接业务”的顺序讲清楚并给出可复制的代码模板和一套通用验证流程。先给结论这篇文章适合正在从“会调 API”走向“能独立搭一个 AI 应用”的开发者。你会搞清楚每个名词实际解决什么问题、它们的调用顺序是什么、如何最小化地搭一个 RAG 知识库、如何给 Agent 加工具调用以及踩到显存不足、接口超时、检索质量差这类问题时从哪里入手排查。1. 核心能力速览先把整条技术栈和本文覆盖范围放在一张表里方便你判断哪些内容可以直接拿走用能力项说明技术栈范围Prompt 工程、Embedding、向量数据库、RAG、LangChain/LangGraph、Agent、工具调用、API 服务核心价值让大模型使用私有知识、自主决定调用工具、提供可复用的应用接口运行环境Python 3.9本地或服务器部署均可CPU 可跑 Embedding 与小型模型GPU 决定生成模型和向量化速度关键依赖langchain、langchain-openai / langchain-community、chromadb、fastapi、sentence-transformers 等具体版本需按项目锁定是否支持 API 服务支持可用 FastAPI 或 LangServe 封装统一接口是否支持批量任务支持建议用目录批量导入文档、队列化检索请求、加入失败重试是否支持一键启动可以写一个启动脚本统一加载向量库和 Web/API 服务但不如整合包一键启动需要简单配置适合场景企业知识库问答、文档阅读理解、Agent 自动化工单、代码审查辅助、内容生产不适合场景对实时性和精度要求极高的生产系统、需要强多轮状态管理的复杂业务需引入 LangGraph 等状态机方案从材料看这篇讨论的是一个偏“全链路方法论”的东西不是某个固定开源仓库。所以本文会用通用开源组件LangChain、ChromaDB、FastAPI 等搭一条可运行链路并标明哪些地方需要按你的项目替换。2. 这条技术栈到底解决什么问题很多新手容易被名词淹没。先把每个词对应到实际问题上。2.1 Embedding 与向量数据库让机器比对“语义”大模型本身不知道你的私有文档内容。要让模型回答“我们公司报销制度是什么”第一步是把文档切成片段转成向量Embedding存进向量数据库。查询时也把问题转成向量用相似度检索出最相关的文档片段。这里的关键事实Embedding 模型决定了检索质量上限。同一个项目里用通用 Embedding 模型和用针对领域微调的 Embedding 模型检索结果会有明显差异。如果材料里涉及“qwen embedding”“deepseek embedding ragflow”这类热词说明当前常见的做法是优先尝试国产开源 Embedding 模型或者 RagFlow、Dify 这类平台内置的向量化链路。2.2 RAG把检索结果塞进提示词RAG 的全称是 Retrieval-Augmented Generation检索增强生成。它做的事很朴素把向量数据库检索到的文本片段拼进 Prompt再让大模型基于这些片段回答。RAG 的价值是“不重新训练模型就能让模型用到私有知识”。缺点是引入了一个新的故障点检索不准回答就不准。所以后面第 5 节会专门讲“如何判断 RAG 质量”。2.3 Agent 与工具调用让模型自己决定下一步Agent 的思路是给模型一些“工具”让它根据任务自动决定调用哪个。常见工具包括搜索引擎、计算器、数据库查询接口、内部 API、代码执行器。材料里热词提到“LangGraph 和 LangChain 的区别”。简单理解LangChain 提供组件库能快速搭简单链式调用LangGraph 提供更精细的图状态管理适合复杂 Agent 流程。先跑通 LangChain 的 Agent再根据需求考虑是否切到 LangGraph。2.4 LangChain不是运行时是胶水层LangChain 不是一个独立的大模型引擎它更像是把 Prompt、LLM、Embedding、向量库、工具、Agent 串起来的框架。它解决的问题不是“模型能力”而是“工程集成速度”。如果项目规模到一定程度也可以只用手写 Python 组装但不是从 0 到 1 最省力的路径。3. 环境准备与前置条件在写代码前先把环境准备好。建议第一次跑通不要追最新版本用稳定组合。以下是通用检查清单实际版本号需要以你使用的模型和框架为准。3.1 基础环境检查# 查看 Python 版本建议 3.9 以上 python --version # 查看 pip 版本 pip --version # 查看 CUDA 是否可用有 NVIDIA 显卡时 nvidia-smi如果你在本地没有 NVIDIA 显卡也可以纯 CPU 跑完整条链路。Embedding 模型和小规模文本生成的推理在 CPU 上只是慢不是不能跑。如果你的业务要求吞吐量再考虑 GPU。3.2 安装核心依赖pip install langchain langchain-community langchain-openai chromadb sentence-transformers fastapi uvicorn python-dotenv如果你的 LLM 调用走 OpenAI 兼容接口就装langchain-openai如果直接调用本地模型通常需要配合 Ollama 或 vLLM 提供的 OpenAI 兼容服务配置好base_url即可。3.3 模型准备整条链路需要两类模型模型类型作用可选方案Embedding 模型文本转向量sentence-transformers 系列、BAAI/bge 系列、开源 Qwen Embedding 等LLM生成答案OpenAI 兼容 API、本地 Ollama 中的 Qwen/Llama/DeepSeek 等需要特别注意Embedding 模型和 LLM 是独立的。你可以用本地 Embedding 模型 远程 LLM API 的组合也可以用远程 Embedding 本地 LLM。如果机器显存有限最省显存的做法是 Embedding 用小模型生成模型用 API。如果你所在环境是特定的国产加速卡或服务器环境例如热门词里提到的昇腾 910B 等vLLM 启动 embedding 模型时可能遇到兼容性问题。从通用实践看vLLM 的推理后端对 embedding 模型支持并不像一个标准的 chat 模型那样通用遇到这类情况优先查阅对应版本的官方文档确认该版本是否支持 embedding 模型必要时换用 sentence-transformers 或独立部署 embedding 服务。4. 动手拆解Embedding 向量数据库 RAG4.1 数据准备如何加载文档并切分RAG 链路的第一步是文档加载。常见做法是读取本地目录里的 txt、md、pdf 等文件。from langchain_community.document_loaders import DirectoryLoader, TextLoader from langchain.text_splitter import RecursiveCharacterTextSplitter loader DirectoryLoader( ./docs, glob**/*.md, loader_clsTextLoader, loader_kwargs{encoding: utf-8} ) documents loader.load() splitter RecursiveCharacterTextSplitter( chunk_size500, chunk_overlap50 ) chunks splitter.split_documents(documents) print(f文档块数量: {len(chunks)})这段代码里chunk_size和chunk_overlap是 RAG 效果的重要参数。块太小会丢失上下文块太大检索噪声高。一般来说500 到 800 字是常见起点具体要看你的文档类型。如果涉及 3GPP 协议、法律合同这类专业长文档建议用更结构化的切分策略先按章节标题切再按段落切。4.2 向量化并写入向量数据库材料里出现了 ChromaDB、Milvus、Qdrant、PGVector 等多个向量数据库热词。从 0 到 1 最省事的是 ChromaDB单机嵌入式不需要额外起服务。from langchain_community.embeddings import HuggingFaceEmbeddings from langchain_community.vectorstores import Chroma embedding_model HuggingFaceEmbeddings( model_nameBAAI/bge-small-zh-v1.5, model_kwargs{device: cpu} ) vectorstore Chroma.from_documents( documentschunks, embeddingembedding_model, persist_directory./chroma_db ) print(向量库写入完成)这里 model_name 需要替换成你实际能下载到的模型。bge-small-zh-v1.5是一个常见中文 Embedding 模型但模型版本会更新实际使用时以你拉取到的模型为准。如果你打算用 Milvus、Qdrant 或 PGVector思路一样初始化向量库客户端替换Chroma为对应类即可。4.3 检索测试看召回是否合理不要急着写回答生成先单独测试检索。这一步能帮你尽早发现知识库问题。question 报销流程是什么 results vectorstore.similarity_search_with_score(question, k5) for doc, score in results: print(f相似度: {score:.4f}) print(doc.page_content) print(---)判断标准很简单检索出来的片段是否真的和问题相关。如果相关片段排在最前面说明 Embedding 和切分策略基本可用如果完全不相关问题可能出在模型选型、数据切分或文档噪音上。4.4 组装 RAG 回答链路检索没问题之后再让 LLM 基于检索结果生成回答。from langchain_openai import ChatOpenAI from langchain.prompts import ChatPromptTemplate from langchain_core.runnables import RunnablePassthrough llm ChatOpenAI( modelqwen2.5:7b, # 按你实际用的模型服务调整 base_urlhttp://127.0.0.1:11434/v1, # Ollama 默认 OpenAI 兼容地址 api_keyEMPTY, temperature0.2 ) retriever vectorstore.as_retriever(search_kwargs{k: 5}) prompt ChatPromptTemplate.from_messages([ (system, 你是一个基于知识库回答问题的助手。只使用下面检索到的内容回答如果内容不足以回答请如实说明。), (human, 检索片段\n{context}\n\n问题{question}) ]) rag_chain ( {context: retriever, question: RunnablePassthrough()} | prompt | llm ) answer rag_chain.invoke(报销流程是什么) print(answer.content)注意base_url和api_key需要按你的模型服务调整。Ollama 是常见本地模型启动方式之一它提供的接口兼容 OpenAI 格式所以ChatOpenAI可以接入如果用 vLLM 启动模型同理替换为 vLLM 服务的地址。5. 如何判断 RAG 质量别只看“答得对不对”热门词里有一个问题“RAG 知识库指标有哪些如何理解各指标”。这部分内容比较核心单独提出来讲。RAG 的质量可以拆成两段检索质量和生成质量。5.1 检索质量指标指标含义怎么理解RecallK前 K 个检索结果中相关文档占全部相关文档的比例越高越好说明没漏掉关键内容PrecisionK前 K 个检索结果中相关文档的比例越高越好说明检索噪声低MRR第一个相关结果出现的位置越高越好说明用户最快看到正确答案Hit Rate是否有相关结果出现在前 K 个评估用户是否能检索到正确答案5.2 生成质量指标生成质量不能用单一数字衡量。常见做法是构建一个测试集问题、标准答案、参考来源用 LLM 作为裁判进行评估或者人工抽检。指标含义忠实度回答是否完全基于检索片段避免幻觉相关性回答是否直接回应了用户问题完整性关键信息是否都覆盖引用正确性回答引用的来源是否真的支撑了对应内容5.3 提高 RAG 质量的实操顺序先看检索结果再做生成优化。检索不对Prompt 写得再好也没用。优化文档切分。按文档结构切比固定字数切通常更有效。换个 Embedding 模型试试。不用迷信大模型Embedding 模型对检索影响很大。加入查询改写。用户问题太口语化时先让 LLM 把问题改写成更利于检索的表述。建立测试集。每次改动之后跑一遍测试集用指标看是变好还是变差。6. Agent 与工具调用让模型不只“会聊天”跑通 RAG 之后再来看 Agent。Agent 解决的是“模型需要外部动作才能完成任务”的场景比如查数据库、查天气、调用内部 API、执行代码。6.1 React Agent 的最小实现LangChain 里 Agent 的最小写法通常包含LLM、工具列表、Agent 执行器。from langchain.agents import create_tool_calling_agent, AgentExecutor from langchain.tools import tool from langchain_core.prompts import ChatPromptTemplate tool def get_service_status(service_name: str) - str: 查询指定服务的当前状态例如 auth-service。 # 这里替换成真实的内部 API 调用或数据库查询 return f{service_name} 状态正常最近 5 分钟无错误日志。 tools [get_service_status] prompt ChatPromptTemplate.from_messages([ (system, 你是自动化运维助手。根据需要调用工具。), (human, {input}), (placeholder, {agent_scratchpad}) ]) agent create_tool_calling_agent(llm, tools, prompt) agent_executor AgentExecutor(agentagent, toolstools, verboseTrue) result agent_executor.invoke({input: 帮我查一下 auth-service 的状态}) print(result[output])这段代码是关键模式tool装饰器把普通函数变成 Agent 可调用的工具。工具的描述信息很重要模型靠描述决定什么时候调用哪个工具。描述不清晰工具就不会被正确调用。6.2 工具设计原则工具描述要写清楚“什么时候用”和“返回什么”。工具参数越少越好减少模型填错参数的概率。工具内部要做好异常处理返回给模型的必须是可读的结果不是堆栈。敏感操作要加确认步骤不要直接把删除、写库、支付之类的动作暴露给模型。6.3 LangChain 还是 LangGraph热词里频繁出现的“langgraph 和 langchain 的区别”从选型角度给你一个判断依据如果你的流程是“用户提问 - 检索 - 生成”用 LangChain 的链式调用就够。如果你的流程包含循环、多分支、定时重试、人工审批用 LangGraph 更合适。Agent 流程复杂之后状态管理会变成痛点LangGraph 能把每一步的状态和流转显式表达出来。第一次做 Agent 项目先用 LangChain 快速验证不要一上来就引入图框架。顺带回应另一个热词“langchain 过时了吗”。从社区活跃度和生态看LangChain 仍然是文档最全、资料最多的框架之一。它适合做快速原型和标准链路。真正“过时”的说法主要来自复杂生产项目对性能和状态管理的高要求那是 LangGraph 或其他更轻量框架的适用场景不代表 LangChain 没有价值。7. 接口 API 与批量任务从 0 到 1 的项目最终都要面对“怎么给别人用”。建议把 RAG 和 Agent 都封装成 FastAPI 接口再批量处理文档。7.1 FastAPI 封装from fastapi import FastAPI from pydantic import BaseModel app FastAPI(titleRAG Service) class QueryRequest(BaseModel): question: str top_k: int 5 class QueryResponse(BaseModel): answer: str sources: list[str] app.post(/rag/query, response_modelQueryResponse) def rag_query(req: QueryRequest): docs retriever.get_relevant_documents(req.question) answer rag_chain.invoke(req.question) return QueryResponse( answeranswer.content, sources[doc.page_content for doc in docs] ) app.get(/health) def health(): return {status: ok}启动服务uvicorn app:app --host 0.0.0.0 --port 80007.2 用 Python 调用接口做批量测试批量任务的核心是控制并发和记录日志。不要一次性把几千个请求全部打进去先小批量测试。import requests import time import json url http://127.0.0.1:8000/rag/query questions [ 报销流程是什么, 如何申请假期, 渠道合作邮件怎么写 ] results [] for q in questions: try: resp requests.post(url, json{question: q}, timeout60) result resp.json() results.append({question: q, answer: result[answer]}) print(f成功: {q}) except Exception as e: results.append({question: q, error: str(e)}) print(f失败: {q}, 错误: {e}) time.sleep(0.5) with open(batch_results.json, w, encodingutf-8) as f: json.dump(results, f, ensure_asciiFalse, indent2)7.3 批量文档导入生产环境常见做法是用任务队列如 Celery处理文档导入接收文件 - 切分 - 向量化 - 写入向量库 - 更新索引。小项目可以简单点用目录扫描加日志记录# 伪代码示例实际路径需按项目调整 python ingest.py --input ./documents --output ./chroma_db --chunk-size 500建议每个文档写入后记录对应doc_id这样后续可以按文档维度更新或删除向量避免“只能加不能删”的尴尬。8. 资源占用与性能观察这一节重点讲怎么看资源占用而不是给你一个固定的显存数字。因为实际占用取决于 Embedding 模型、LLM 大小、量化方式、并发数等必须落到你的具体环境上看。8.1 观察方法# 查看 GPU 显存占用 nvidia-smi -l 1 # 查看 CPU 和内存 htop # Python 进程内存 ps aux | grep python8.2 性能影响因子因素影响方向Embedding 模型尺寸越大越准但向量化速度变慢CPU 上更明显LLM 参数量和量化位宽直接影响显存占用和推理速度chunk_size越大上下文信息越多但检索和生成 token 开销增加top_k越大召回越多但 Prompt 变长首 token 延迟增加并发请求影响吞吐量但可能触发显存溢出或排队超时8.3 降低资源占用的思路如果 Embedding 和 LLM 都在本机 GPU 上跑显存容易紧张。可以把 Embedding 放到 CPU推理放在 GPU。LLM 优先选 4-bit 量化版本用 Ollama 或 vLLM 加载时指定量化参数。批量向量化时用 batch size 控制峰值显存。接口服务设置超时和并发上限避免资源被个别慢请求占满。8.4 关于 vLLM 与 Embedding 的常见限制热词里出现了“通过 vLLM 启动 embedding 向量和 reranker 模型”的疑问。这里补充一个通用认知vLLM 的服务目标主要面向生成模型对 embedding 和 reranker 模型的支持不是它最核心的能力。在不同硬件、不同版本下能不能用 vLLM 启动 embedding 模型表现不一致。如果你在某个服务器上遇到这类问题更稳妥的方案是Embedding 模型单独用 sentence-transformers 启动提供 HTTP 接口。Reranker 模型同样单独部署服务或直接跳过。生成模型继续用 vLLM两者互不干扰。这样能避免一个框架承载所有模型类型的兼容性风险。9. 常见问题与排查方法问题现象可能原因排查方式解决方案依赖安装失败Python 版本过老或新、包名变更查看完整错误堆栈确认是网络问题还是版本冲突升级 Python 到 3.9换用国内镜像源锁定版本向量库写入后检索结果为空Embedding 模型加载失败或切分后文档块为空打印 chunks 数量和向量库统计检查文档读取路径和编码确认文档不是空文件检索结果相关度差Embedding 模型选型不当或 chunk_size 不合适单独跑相似度检索人工检查召回换 Embedding 模型调整切分参数接口调用超时LLM 推理慢或请求队列堆积在日志里看单次推理耗时降低并发换更小的模型启用流式输出显存不足模型过大或并发过高观察 nvidia-smi 峰值换量化模型降低 batch 并发Embedding 放 CPUAgent 不调用工具工具描述不清晰或模型不支持工具调用检查 verbose 日志中模型输出改写工具描述换支持 function call 的模型批量任务卡住单个请求无超时或循环逻辑里依赖失败加日志定位卡在哪一步所有请求加 timeout任务加失败重试和死信标记回答产生幻觉检索片段不完整或 Prompt 约束不足把实际 Prompt 打出来检查加强 Prompt 限制提高 top_k增加引用来源端口被占用上次服务未退出或其他进程占用端口lsof -i:8000或netstat -ano查看换端口或清理旧进程模型服务地址不对导致 401/404base_url 或 api_key 配错先用 curl 直接请求模型服务测试核对模型服务文档测试后再接 LangChain10. 最佳实践与使用建议第一个版本用最小配置跑通。先不用管性能和多轮对话把“文档 - 向量库 - 检索 - 回答 - 接口”这条链路完整走一遍。统一目录结构。模型下载目录、文档目录、向量库目录、日志目录分开管理后续更新和排查会省很多时间。每次修改都建立基线测试集。无论是调 Prompt、换 Embedding 还是改切分参数都用同一组问题跑结果对比之后再上线。批次任务一定要加日志和失败重试机制。没有日志的批处理任务出问题时定位成本会翻倍。接口服务不要直接暴露到公网。有公网访问需求时务必加鉴权、限流和来源 IP 限制。涉及私有数据、用户信息、公司制度文档时确认数据使用范围和合规边界。不能确认来源的文档不要进入知识库。涉及人脸、声音、姓名等个人敏感信息的内容在采集、存储、生成、分发前必须确认授权遵守当地法规和平台规则。商用发布前对 Agent 的自动动作做权限最小化设计。不要给模型调用删除、支付、发布等高危操作的能力。上线后持续抽检真实问题。RAG 不是一次配置就永久有效的系统文档更新、用户问题分布变化都会影响效果。11. 总结与下一步从 0 到 1 搭建大模型应用项目真正的难点不是某个算法而是把 Embedding、向量数据库、RAG、LangChain、Agent 工具调用这条链路串起来之后还能稳定、可排查、可迭代。这篇文章最值得你记住的路线是先跑通文档加载和切分再验证向量检索召回再组装 RAG 回答链路最后封装 API 和批量任务。Agent 放在 RAG 之后做因为工具调用的前提是模型对一个领域有足够理解而 RAG 正好能给它提供这种理解。最先应该验证的功能不是一段华丽的多轮对话而是“检索出的内容是否足够回答问题”。这一步能帮你提前排除 Embedding 选型、切分策略和文档清洗的问题。最容易踩的坑有三类一是 Embedding 模型和 LLM 混为一谈用同一个模型服务启动所有功能二是不做检索质量评估直接调 Prompt效果反复横跳三是一上来就追 LangGraph 和复杂 Agent 架构流程还没跑通就把自己绕进去。后续可以继续扩展的方向包括用 LangGraph 处理有状态的多智能体协作、引入 Reranker 提升检索精度、用评估框架给 RAG 建立自动化测试集、针对专业领域如协议文档、法律文书做结构化切分和知识抽取。建议你先照着第 4 节的代码拿自己手头的文档跑一遍最小链路。跑通之后再回头决定要加 Agent、换向量库还是接入生产环境。这套链路只要起过一次后面扩展都是增量工作。
返回列表