
这类教程最值得先看的不是功能列表而是能不能在普通开发环境里把流程串起来。LangChain、LangGraph、LLaMA-Factory、RAG、MCP、Agent这些词单看都懂但新手最容易卡在第一步环境依赖冲突、版本不匹配、模型路径不对、接口调不通。我建议先从最核心的链路开始把“本地模型微调 - 构建知识库 - 用Agent调度”这条主路跑通再去考虑复杂的图状态和MCP工具集成。如果你手头有能跑动7B参数模型的GPU环境显存8G以上或者有足够的耐心在CPU上测试小模型那么跟着下面的步骤可以在一天内搭建起一个可对话、可查询私有文档的AI应用原型。整个过程的关键不是代码多复杂而是理清每个组件的输入输出和它们之间的数据流转。1. 先理清技术栈分工谁负责什么数据怎么流看到一堆框架名别慌它们各有明确的职责边界。混用或者顺序错了就会导致模型加载了却无法调用或者知识库建好了但Agent找不到。1.1 核心组件角色定义LLaMA-Factory 负责“练兵”。它的核心任务是对开源大语言模型如Llama、Qwen、ChatGLM进行微调Fine-tuning。你给它一批标注好的对话数据或指令数据它帮你调整模型参数让模型更擅长某个特定领域或风格。它不直接对外提供对话服务而是产出微调后的模型文件通常是.bin或.safetensors格式。RAG检索增强生成知识库 负责“查资料”。当用户问一个具体问题时比如“公司2024年Q3的财报要点是什么”RAG系统不会让模型凭空编造。它会先从你提前准备好的文档PDF、Word、TXT等中检索出最相关的几个片段然后把“问题相关片段”一起交给模型去生成答案。这大大减少了模型胡言乱语幻觉的可能。LangChain提供了构建RAG系统所需的各种模块文档加载、切分、向量化、检索。LangChain 负责“组装流水线”。它是一个框架提供了连接大模型、记忆、工具、数据检索等组件的标准化接口。你可以用LangChain快速搭建一个链Chain比如“用户输入 - 检索知识库 - 拼接提示词 - 调用模型 - 返回输出”。它是胶水把各个功能粘合起来。LangGraph 负责“管理复杂流程”。当你的AI应用不是简单的一问一答而是需要多步骤决策、循环、分支或者长期记忆时简单的Chain就不够用了。LangGraph允许你用图Graph的方式来定义工作流节点是执行步骤边是流转条件。它特别适合构建有状态的、复杂的智能体Agent。MCPModel Context Protocol 负责“连接外部工具”。你可以把它理解为一个标准化的“工具插槽”协议。通过MCPAI智能体可以安全、规范地调用外部工具比如查询数据库、执行代码、操作文件系统。它让Agent的能力从纯文本生成扩展到了可操作现实世界的数据和系统。Agent智能体 是最终呈现给用户的“大脑”。它利用LangChain或LangGraph编排的流程结合微调后的模型来自LLaMA-Factory、知识库来自RAG和工具通过MCP理解用户意图规划步骤执行任务并给出最终答复。1.2 数据流转主链路一个典型的开发流程是这样的准备与微调 用LLaMA-Factory基于你的领域数据微调一个基础模型得到专属模型A。构建知识库 用LangChain处理你的私有文档切片、向量化后存入向量数据库如Chroma、Milvus建成知识库B。装配智能体用LangChain定义一个RAG Chain它内部会去查询知识库B。将微调后的模型A设置为这个Chain的LLM大语言模型核心。如果需要多步骤或工具调用用LangGraph将这个Chain和MCP工具封装成一个更复杂的Agent。提供服务 将装配好的Agent暴露为API如用FastAPI、Flask或交互式界面。理清这个关系你就知道该按什么顺序动手了。接下来我们从环境准备开始。2. 环境准备避开依赖地狱从干净环境开始很多教程失败在第一步。Python包版本冲突、CUDA版本不匹配、系统权限问题足以消耗掉大部分热情。我的建议是优先使用Conda创建独立的虚拟环境。2.1 基础环境搭建假设你的开发机是Ubuntu 20.04/22.04或Windows WSL2并有一张NVIDIA显卡CPU模式也可但慢。# 1. 创建并激活虚拟环境Python 3.10是一个兼容性较好的版本 conda create -n ai-agent python3.10 -y conda activate ai-agent # 2. 安装PyTorch务必去官网https://pytorch.org/根据你的CUDA版本选择命令 # 例如CUDA 11.8的安装命令可能如下 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 3. 安装LangChain和LangGraph核心包 pip install langchain langgraph langchain-community # 4. 安装向量数据库客户端这里以轻量级的Chroma为例 pip install chromadb # 5. 安装文档加载器相关包用于处理PDF、Word等 pip install pypdf python-docx markdown unstructured # 6. 安装Web框架用于提供API服务 pip install fastapi uvicorn2.2 LLaMA-Factory专项安装LLaMA-Factory的依赖相对独立且对Transformer版本有特定要求。最好不要和上面的环境混用我建议单独为其创建一个环境或者在一个环境内精心管理版本。# 在ai-agent环境内安装LLaMA-Factory # 注意这里可能会与之前安装的langchain等包产生版本冲突如果冲突优先保证LLaMA-Factory所需版本 git clone https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory pip install -e .[torch,metrics] # 安装过程中如果提示某个包版本冲突可以尝试先卸载冲突包再重新安装指定版本关键检查点安装完成后在Python中执行import transformers和import datasets确保没有报错。LLaMA-Factory的运行严重依赖这两个库的特定版本。2.3 模型下载与准备微调需要基础模型。从Hugging Face下载模型是常规操作但国内网络可能不稳定。方案一推荐使用镜像 配置Hugging Face镜像。# Linux/Mac export HF_ENDPOINThttps://hf-mirror.com # Windows (cmd) set HF_ENDPOINThttps://hf-mirror.com # Windows (PowerShell) $env:HF_ENDPOINThttps://hf-mirror.com之后使用huggingface-cli download或代码中指定cache_dir下载会走镜像。方案二 手动下载。在镜像站或能访问的源找到模型文件如Qwen/Qwen2.5-7B-Instruct下载到本地目录后续在LLaMA-Factory和LangChain中指定本地路径。对于初步实验建议选择一个小尺寸的模型如Qwen2.5-1.5B或Llama-3.2-3B这样对显存要求低微调速度快。3. 第一步实战用LLaMA-Factory微调你的第一个模型不要一开始就想微调一个大模型。我们的目标是验证流程。准备一个极小的、格式正确的数据集。3.1 准备微调数据创建一个JSON文件train.jsonl每行是一个对话样本。LLaMA-Factory通常支持alpaca指令-输出或sharegpt多轮对话格式。Alpaca格式示例{ instruction: 翻译以下英文句子为中文。, input: Hello, world!, output: 你好世界 }ShareGPT格式示例{ conversations: [ {role: human, content: 谁是中国第一位航天员}, {role: assistant, content: 中国第一位航天员是杨利伟。} ] }准备5-10条这样的数据保存为train.jsonl。这足以让你跑通微调流程。3.2 配置与启动微调LLaMA-Factory提供了Web UI和命令行两种方式。对于首次验证命令行更直接。# 进入LLaMA-Factory目录 cd path/to/LLaMA-Factory # 使用LoRA一种参数高效的微调方法快且省显存进行微调 # 假设你的数据在 ./data/train.jsonl基础模型是下载好的 Qwen2.5-1.5B # 模型路径替换为你自己的实际路径 CUDA_VISIBLE_DEVICES0 python src/train_bash.py \ --stage sft \ --model_name_or_path /path/to/Qwen2.5-1.5B \ --do_train \ --dataset train_data \ --dataset_dir ./data \ --template qwen2.5 \ --finetuning_type lora \ --lora_target all \ --output_dir ./output/qwen_finetuned \ --overwrite_cache \ --per_device_train_batch_size 2 \ --gradient_accumulation_steps 4 \ --lr_scheduler_type cosine \ --logging_steps 10 \ --save_steps 100 \ --learning_rate 5e-5 \ --num_train_epochs 3.0 \ --plot_loss \ --fp16参数关键解读--stage sft: 执行监督微调。--finetuning_type lora: 使用LoRA微调这是首选因为它只训练少量参数速度快显存占用小且能保持模型原有知识。--per_device_train_batch_size和gradient_accumulation_steps: 共同决定有效批次大小。如果显存不足OOM首先降低batch_size。--fp16: 使用半精度浮点数训练进一步节省显存。如果显卡支持可以尝试--bf16。--output_dir: 微调后的模型实际上是LoRA权重会保存在这里。运行后观察命令行应开始输出损失loss日志。如果loss稳步下降说明训练在进行。检查output_dir下是否生成了adapter_model.binLoRA权重文件和adapter_config.json。最重要的一步尝试加载并测试微调后的模型。LLaMA-Factory提供了推理脚本。python src/cli_demo.py \ --model_name_or_path /path/to/Qwen2.5-1.5B \ --adapter_name_or_path ./output/qwen_finetuned \ --template qwen2.5在打开的CLI界面中输入你训练数据里类似的问题看模型是否能给出符合预期的回答。如果能恭喜你第一步成功了。4. 第二步实战用LangChain构建RAG知识库微调让模型“更懂行”RAG则让模型“有资料可查”。我们构建一个能查询本地文档的知识库。4.1 文档加载与处理假设你有一个knowledge_base文件夹里面放了一些.txt、.pdf或.md文件。from langchain_community.document_loaders import DirectoryLoader, TextLoader, PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter # 1. 加载文档以txt和pdf为例 txt_loader DirectoryLoader(./knowledge_base, glob**/*.txt, loader_clsTextLoader) pdf_loader DirectoryLoader(./knowledge_base, glob**/*.pdf, loader_clsPyPDFLoader) documents [] documents.extend(txt_loader.load()) documents.extend(pdf_loader.load()) print(fLoaded {len(documents)} documents.) # 2. 分割文本 # 大模型有上下文长度限制必须把长文档切分成小块chunks text_splitter RecursiveCharacterTextSplitter( chunk_size500, # 每个块大约500字符 chunk_overlap50 # 块之间重叠50字符避免语义被切断 ) chunks text_splitter.split_documents(documents) print(fSplit into {len(chunks)} chunks.)4.2 向量化与存储将文本块转换为向量嵌入并存入向量数据库。from langchain_community.embeddings import HuggingFaceEmbeddings from langchain_community.vectorstores import Chroma # 3. 选择嵌入模型本地运行无需API Key # 使用一个轻量级且效果不错的开源模型 embedding_model HuggingFaceEmbeddings( model_nameBAAI/bge-small-zh-v1.5, # 中文小模型适合本地 model_kwargs{device: cpu}, # 如果没有GPU用cpu encode_kwargs{normalize_embeddings: True} ) # 4. 创建向量数据库 vector_db Chroma.from_documents( documentschunks, embeddingembedding_model, persist_directory./chroma_db # 数据持久化到本地目录 ) print(Vector database created and persisted.)4.3 构建检索链现在我们可以创建一个简单的链输入问题 - 检索相关文档 - 组合成提示词 - 调用模型 - 生成答案。from langchain.chains import RetrievalQA from langchain.prompts import PromptTemplate # 注意这里需要调用我们微调过的模型。我们用HuggingFacePipeline包装它。 from langchain_community.llms import HuggingFacePipeline import torch from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline # 5. 加载我们微调过的模型 model_path /path/to/Qwen2.5-1.5B # 基础模型路径 adapter_path ./output/qwen_finetuned # LoRA权重路径 tokenizer AutoTokenizer.from_pretrained(model_path) model AutoModelForCausalLM.from_pretrained( model_path, torch_dtypetorch.float16, device_mapauto, ) # 加载LoRA权重这里需要根据你使用的微调框架的加载方式LLaMA-Factory通常使用peft from peft import PeftModel model PeftModel.from_pretrained(model, adapter_path) # 创建文本生成管道 pipe pipeline( text-generation, modelmodel, tokenizertokenizer, max_new_tokens512, temperature0.1, do_sampleTrue, ) llm HuggingFacePipeline(pipelinepipe) # 6. 定义提示词模板 prompt_template 基于以下上下文信息回答用户的问题。如果你不知道答案就说你不知道不要编造答案。 上下文 {context} 问题{question} 答案 PROMPT PromptTemplate( templateprompt_template, input_variables[context, question] ) # 7. 创建检索问答链 qa_chain RetrievalQA.from_chain_type( llmllm, chain_typestuff, # 简单地将所有检索到的上下文塞进提示词 retrievervector_db.as_retriever(search_kwargs{k: 3}), # 检索最相关的3个块 chain_type_kwargs{prompt: PROMPT}, return_source_documentsTrue # 返回参考来源便于调试 ) # 8. 进行查询 question 你的知识库中提到了哪些关键概念 result qa_chain.invoke({query: question}) print(Answer:, result[result]) print(\nSource Documents:) for doc in result[source_documents]: print(f- {doc.page_content[:200]}...)如果这一步能成功运行并返回基于文档的答案那么你的“微调模型RAG知识库”核心引擎就搭建完成了。5. 第三步实战用LangGraph构建有状态的智能体Agent前面的RetrievalQA是一个链一次调用完成问答。但现实任务更复杂比如用户说“帮我总结最近三篇文档的要点然后写一封邮件”。这需要分解任务、多次调用工具、并记住中间状态。这时就需要LangGraph。5.1 定义图状态和节点我们构建一个简单的Agent它可以选择使用“RAG查询”或“通用聊天”两个工具之一。from typing import TypedDict, Annotated, List from langgraph.graph import StateGraph, END import operator # 定义图的状态结构 class AgentState(TypedDict): question: str # 用户原始问题 context: str # 检索到的上下文来自RAG answer: str # 最终答案 steps: List[str] # 记录执行步骤用于观察 # 定义节点函数 def retrieve_node(state: AgentState): RAG检索节点 # 这里复用我们之前创建的vector_db docs vector_db.similarity_search(state[question], k3) context \n\n.join([doc.page_content for doc in docs]) return {context: context, steps: state[steps] [Retrieved relevant documents.]} def generate_node(state: AgentState): 答案生成节点 # 根据是否有上下文选择不同的提示词 if state[context]: prompt f基于以下信息回答问题。 信息{state[context]} 问题{state[question]} 答案 else: prompt f请回答以下问题。 问题{state[question]} 答案 # 调用我们微调的模型 response llm.invoke(prompt) return {answer: response, steps: state[steps] [Generated answer.]} def router_node(state: AgentState): 路由节点决定是否需要检索 # 一个简单的规则如果问题包含“文档”、“文件”、“知识库”等词则走检索分支 need_retrieve_keywords [文档, 文件, 知识库, 资料, 根据] question state[question] if any(keyword in question for keyword in need_retrieve_keywords): return retrieve else: # 直接生成将上下文置空 return generate_directly5.2 构建并运行图# 创建图构建器 workflow StateGraph(AgentState) # 添加节点 workflow.add_node(retrieve, retrieve_node) workflow.add_node(generate, generate_node) workflow.add_node(generate_directly, generate_node) # 另一个生成节点但上下文为空 # 设置入口点 workflow.set_entry_point(router) # 添加边定义流程流转 workflow.add_conditional_edges( router, router_node, # 路由函数决定下一个节点 { retrieve: retrieve, generate_directly: generate_directly } ) workflow.add_edge(retrieve, generate) workflow.add_edge(generate, END) workflow.add_edge(generate_directly, END) # 编译图 app workflow.compile() # 运行图 initial_state {question: 知识库中关于LangGraph的部分讲了什么, steps: [], context: , answer: } result app.invoke(initial_state) print(Final Answer:, result[answer]) print(Execution Steps:, result[steps])这个简单的图实现了条件判断问题需要知识库就检索后生成否则直接生成。LangGraph的强大之处在于你可以轻松扩展这个图加入循环直到满足条件、并行执行、调用MCP工具等。6. 关键配置、排查与生产化思考跑通Demo只是开始。要让这个系统稳定可用你需要关注以下方面。6.1 模型与显存管理显存估算 7B参数模型FP16精度加载大约需要14GB显存。使用LoRA微调时可训练参数很少但基础模型仍需加载。如果显存不足使用--load_in_4bit或--load_in_8bit量化加载。使用更小的模型如1.5B、3B。使用CPU卸载速度慢。模型加载 LangChain的HuggingFacePipeline有时会与微调框架的模型加载方式冲突。如果遇到问题尝试先直接用transformers的pipeline生成再封装给LangChain。6.2 RAG知识库优化分块Chunking策略chunk_size500是通用设置。对于技术文档可能需要更大1000对于对话记录可能更小200。需要根据文档特点和模型上下文窗口调整。检索器Retriever调优search_kwargs{k: 3} 返回前3个相关片段。k值越大信息越全但可能引入噪声且消耗更多上下文长度。尝试不同的检索方法similarity_search余弦相似度、mmr_search最大边际相关性兼顾相关性和多样性。嵌入Embedding模型bge-small-zh是中文不错的起点。如果追求精度可以换用bge-large-zh或text2vec系列但计算开销更大。6.3 LangGraph与Agent进阶工具集成MCP 要让Agent能执行“发邮件”、“查数据库”等操作你需要为这些操作创建MCP Server实现特定接口然后在LangGraph中将它们定义为ToolNode。这涉及到更复杂的协议和安全性设计初期可以先用简单的函数模拟。长期记忆 LangGraph的State可以持久化。你可以将对话历史、用户偏好存入数据库如SQLite、Redis并在每次对话开始时加载到State中实现跨会话记忆。稳定性 复杂的图可能陷入循环或卡住。需要设计超时机制、错误处理节点和人工审核节点Human-in-the-loop。6.4 部署与服务化API服务 用FastAPI将你的appLangGraph编译的应用或qa_chain包装成HTTP接口。from fastapi import FastAPI app_fastapi FastAPI() app_fastapi.post(/chat) async def chat_endpoint(request: dict): question request.get(question) state {question: question, steps: [], context: , answer: } result app.invoke(state) # 调用LangGraph应用 return {answer: result[answer]}并发与性能 模型推理是计算密集型且耗时的。在生产环境需要考虑使用异步处理asyncio避免阻塞。使用模型服务化框架如TGI、vLLM单独部署模型通过API调用实现多请求排队和批处理。为RAG检索和模型推理设置独立的超时和重试。6.5 常见问题排查清单微调时OOM显存不足降低per_device_train_batch_size。开启梯度检查点--gradient_checkpointing。使用更激进的量化如4bit微调。换用更小的模型。RAG检索结果不相关检查嵌入模型是否与文档语言匹配中文文档用中文嵌入模型。调整文本分块的chunk_size和chunk_overlap。尝试在检索前对查询进行重写或扩展Query Expansion。LangGraph图编译或运行错误检查State的类型注解TypedDict是否正确定义了所有字段。确保每个节点函数返回的字典是State的子集。使用workflow.get_graph().draw_mermaid()输出图的可视化检查流程逻辑。模型生成质量差检查提示词Prompt是否清晰传达了任务和格式。调整生成参数temperature调低更确定调高更多样max_new_tokens确保足够长。确认微调数据质量是否足够高、数量是否足够。我个人更建议的开发路径是先用一个非常小的数据集和模型把LLaMA-Factory微调 - LangChain RAG - LangGraph Agent这个完整链路跑通。这个过程中遇到的90%的问题都是环境、路径和版本问题。链路打通后再逐步升级换更大的模型、用更丰富的微调数据、优化RAG分块和检索策略、为Agent添加更实用的工具。这样每一步的进展和问题都清晰可见不会在复杂的配置中迷失方向。