在实际 LLM 应用开发中,开发者常常面临一个困境:知道很多时髦的概念,比如 Prompt、RAG、Agent,但面对一个具体的业务需求时,却不知道如何将这些技术组合起来,形成一个稳定、可交付的项目。从写好一个提示词,到构建一个能理解私有知识、调用工具、自主决策的智能体,中间隔着巨大的工程鸿沟。这不仅仅是理论问题,更是实践问题——如何选择框架、如何设计数据流、如何调试、如何应对生产环境的复杂性。
本文旨在弥合这一鸿沟。我们将以一个“智能技术问答助手”项目为主线,贯穿从基础 Prompt 工程到高级 Agent 开发的完整流程。你将不仅理解每个核心概念(Prompt, RAG, Agent, Skills, MCP)是什么,更将掌握如何将它们串联起来,构建一个具备知识检索、代码生成、安全审查等复合能力的 AI 应用。整个过程强调可复现性,包含具体的代码、配置、命令和排错指南,确保你能在本地环境或开发服务器上跑通整个项目,并理解每一步背后的设计决策。
1. 核心概念解析:从 Prompt 到 Agent 的技术栈演进
在动手之前,必须清晰理解每个技术组件扮演的角色及其在整个系统中的地位。混淆概念会导致架构设计混乱。
1.1 Prompt:与大模型对话的“指令集”
Prompt 是用户提供给大模型的输入文本,它决定了模型的输出方向和风格。你可以把它理解为给一个极其聪明但缺乏背景知识的实习生下达的工作指令。
- 通俗理解:告诉模型“做什么”和“怎么做”的说明书。
- 技术定义:一段结构化的文本,包含任务描述、上下文信息、输出格式要求以及可能的示例(Few-shot Learning)。
- 项目中的作用:它是所有交互的起点。一个糟糕的 Prompt 会导致模型答非所问,而一个优秀的 Prompt 能极大提升输出质量。
- 最小示例:
你是一个专业的 Python 代码助手。请将以下自然语言需求转换为 Python 函数。 需求:计算一个列表中所有偶数的和。 要求:函数名称为 `sum_of_evens`,包含类型注解和文档字符串。 只输出代码,不要解释。 - 常见误解:
- 越长越好:并非如此。无关信息会干扰模型。应追求精确、清晰。
- 一次成型:Prompt 需要迭代优化。通过观察模型输出,不断调整指令和格式。
- 万能钥匙:同一个 Prompt 在不同模型(如 GPT-4、Claude、本地 Llama)上效果可能差异巨大。
1.2 RAG:为模型注入“长期记忆”和“专业知识”
大模型的训练数据是静态的,无法知晓训练截止日期后的新闻、你的私有文档或数据库里的信息。RAG 解决了这个问题。
- 通俗理解:一个给大模型“开卷考试”的机制。先从一个庞大的知识库(你的文档、数据库)里找到相关材料,再连同问题和材料一起交给模型作答。
- 技术定义:检索增强生成。其核心流程为:索引->检索->增强->生成。
- 索引:将原始知识(如 PDF、TXT、Markdown)切分成片段,转换为向量(Embedding),存入向量数据库。
- 检索:当用户提问时,将问题也转换为向量,在向量数据库中查找最相似的几个知识片段。
- 增强:将检索到的相关片段作为上下文,与原始问题拼接,形成一个新的、信息更丰富的 Prompt。
- 生成:将增强后的 Prompt 发送给大模型,得到最终答案。
- 项目中的作用:让我们的“技术问答助手”能够回答关于特定技术栈(如 Spring Boot 3.2 新特性)、公司内部 API 文档等非公开知识。
- 系统原理与重排序:简单的向量检索可能返回相关但不精确的片段。重排序是一个优化步骤,使用一个更精细的模型对初步检索结果进行相关性打分并重新排序,确保最相关的信息排在最前面,显著提升最终答案的准确性。
1.3 Agent & Skills:赋予模型“行动能力”
如果 RAG 是让模型“知道”,那么 Agent 就是让模型“做到”。Agent 是一个具有自主性的系统,它可以理解目标、制定计划、调用工具(Skills)执行动作,并根据结果调整后续行为。
- 通俗理解:一个具备“大脑”(LLM)和“手脚”(Tools/Skills)的智能体。大脑负责思考决策,手脚负责执行具体操作(如搜索网络、运行代码、查询数据库)。
- 技术定义:Agent = LLM(决策核心)+ 规划器(Planning)+ 记忆(Memory)+ 工具集(Tools/Skills)。它通常基于 ReAct(Reasoning and Acting)等框架运行。
- Skills/Tools:即 Agent 可以调用的具体功能。一个 Skill 通常包含:名称、描述、输入参数定义(JSON Schema)、执行函数。
- 项目中的作用:让我们的助手不仅能回答问题,还能执行操作。例如,用户说“帮我写一个 FastAPI 的 POST 接口,并保存到文件
demo.py”,Agent 可以规划步骤:1. 生成代码(调用代码生成 Skill),2. 写入文件(调用文件操作 Skill)。
1.4 MCP:工具调用的“标准化协议”
当你为 Agent 开发 Skills 时,可能会遇到一个问题:不同的 Agent 框架(如 LangChain、LlamaIndex、Hermes)定义和使用 Tool 的方式略有不同。MCP 旨在解决这个问题。
- 通俗理解:一个统一的“插座”标准。任何符合 MCP 标准的 Skill(工具),可以像电器一样,插到任何支持 MCP 的 Agent 框架(插座)上使用。
- 技术定义:模型上下文协议。它标准化了服务器(提供工具)和客户端(LLM/Agent)之间关于工具列表、工具调用和结果返回的通信方式。
- 项目中的作用:提高 Skills 的复用性。我们可以开发一套符合 MCP 的通用 Skills(如计算器、天气查询),然后在不同的 Agent 项目中直接使用,无需重复开发或适配。
1.5 大模型微调:为特定任务“定制大脑”
以上技术都是在“使用”一个现成的大模型。微调则是“改造”模型本身,通过在特定领域的数据集上继续训练,让模型更擅长某一类任务(如法律文书写作、医疗问答)。
- 通俗理解:给一个通才模型进行“专项培训”,让它变成某个领域的专家。
- 技术定义:使用领域数据,以相对较小的计算成本,调整预训练大模型的部分参数(如 LoRA),使其输出更符合特定分布。
- 项目中的定位:成本较高,周期较长。对于大多数应用,优先使用 Prompt Engineering、RAG 和 Agent。当上述方法在特定风格、术语或复杂推理任务上达到瓶颈时,再考虑微调。例如,让模型严格按照公司规定的安全漏洞报告格式进行输出。
2. 环境准备与项目初始化
我们将构建一个名为tech-assistant的智能技术问答助手项目。它首先通过 RAG 获取技术知识,然后通过 Agent 调用 Skills 执行代码生成、文件操作等任务。
2.1 基础环境与工具链
确保你的开发环境满足以下要求:
| 组件 | 要求 | 说明 |
|---|---|---|
| 操作系统 | Linux/macOS/WSL2 (推荐) | Windows 原生可能在某些依赖上遇到问题。 |
| Python | 3.10 - 3.11 | 3.12 可能部分包兼容性不佳,建议使用 3.10。 |
| 包管理 | pip&venv | 强烈建议使用虚拟环境隔离项目依赖。 |
| 版本控制 | Git | 用于代码管理和依赖锁定。 |
| 文本编辑器 | VS Code / PyCharm | 需安装 Python 插件。 |
| 内存 | >= 16GB | 运行本地模型或向量数据库时需要。 |
| 存储 | >= 10GB 空闲空间 | 用于存放模型、向量数据库文件。 |
首先创建项目目录并初始化虚拟环境:
# 创建项目目录 mkdir tech-assistant && cd tech-assistant # 创建虚拟环境(Windows 用户使用 `python -m venv venv`) python3.10 -m venv venv # 激活虚拟环境 # Linux/macOS: source venv/bin/activate # Windows: # venv\Scripts\activate # 升级 pip pip install --upgrade pip2.2 核心依赖选择与安装
我们将选择一个轻量且流行的技术栈:使用LlamaIndex作为 RAG 和 Agent 的核心框架,Chroma作为向量数据库,Ollama来本地运行开源大模型(如 Llama 3.2),MCP协议来标准化 Skills。
创建requirements.txt文件并安装依赖:
# 核心框架 llama-index>=0.10.0 llama-index-llms-ollama llama-index-embeddings-ollama llama-index-vector-stores-chroma # 向量数据库与嵌入模型(通过 Ollama) chromadb # 本地模型服务(运行 Llama 3.2 等) ollama # MCP 相关(用于标准化工具调用) mcp[cli] # 安装 MCP CLI 和基础库 # 其他工具 pypdf # 用于解析 PDF 文档 python-dotenv # 管理环境变量安装依赖:
pip install -r requirements.txt2.3 启动本地模型服务 (Ollama)
我们将使用Ollama在本地运行Llama 3.2模型,它平衡了能力与资源消耗。首先下载并启动 Ollama 服务。
- 安装 Ollama:访问 Ollama 官网 下载对应操作系统的安装包并安装。
- 拉取模型:在终端运行以下命令拉取 Llama 3.2 模型(约 4.7GB)。
ollama pull llama3.2:latest - 验证服务:模型拉取完成后,Ollama 服务会自动启动。可以通过以下命令测试:
如果看到模型回复,说明服务正常。ollama run llama3.2 “Hello, world”
注意:首次运行
ollama run可能会比较慢,因为需要加载模型到内存。确保你的机器有足够可用内存(运行 7B 参数模型建议 8GB+)。
3. 构建 RAG 知识库:让助手“懂”你的技术文档
现在,我们为助手构建一个私有知识库。假设我们有一些关于“FastAPI”和“Pydantic”的技术文档(Markdown 格式)。
3.1 准备知识文档
在项目根目录创建knowledge_base文件夹,并放入你的文档。这里我们创建两个示例文件:
knowledge_base/fastapi_intro.md:
# FastAPI 简介 FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Web 框架,基于标准 Python 类型提示。 主要特性: - **快速**:非常高的性能,与 NodeJS 和 Go 相当。 - **快速编码**:开发速度提高约 200% 至 300%。 - **更少 Bug**:减少约 40% 的人为错误。 - **直观**:强大的编辑器支持,补全无处不在。 - **简短**:代码重复最小化。 - **健壮**:生产级别的代码,带有自动交互式文档。knowledge_base/pydantic_validation.md:
# Pydantic 数据验证 Pydantic 是一个使用 Python 类型注解进行数据验证和设置管理的库。 ## 基础用法 ```python from pydantic import BaseModel class User(BaseModel): id: int name: str = “John Doe”Pydantic 确保id是整数,name是字符串(默认值为 “John Doe”)。
在 FastAPI 中使用
FastAPI 深度集成 Pydantic,用于请求和响应模型的定义与验证。
### 3.2 创建向量索引 我们将使用 `LlamaIndex` 读取文档,通过 `Ollama` 的嵌入模型转换为向量,并存储到 `Chroma` 数据库中。 创建 `rag_indexer.py` 文件: ```python import os from pathlib import Path from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings from llama_index.embeddings.ollama import OllamaEmbedding from llama_index.vector_stores.chroma import ChromaVectorStore from llama_index.core.storage.storage_context import StorageContext import chromadb from dotenv import load_dotenv # 加载环境变量(如果有的话) load_dotenv() # 1. 配置嵌入模型 # 使用 Ollama 提供的 nomic-embed-text 模型,它是一个优秀的开源嵌入模型 Settings.embed_model = OllamaEmbedding(model_name="nomic-embed-text") # 2. 初始化 Chroma 客户端和集合 # persist_directory 指定向量数据库持久化存储的路径 persist_dir = "./chroma_db" chroma_client = chromadb.PersistentClient(path=persist_dir) chroma_collection = chroma_client.get_or_create_collection("tech_knowledge") # 3. 创建向量存储和上下文 vector_store = ChromaVectorStore(chroma_collection=chroma_collection) storage_context = StorageContext.from_defaults(vector_store=vector_store) # 4. 读取文档 documents_path = "./knowledge_base" documents = SimpleDirectoryReader(documents_path).load_data() print(f"已加载 {len(documents)} 个文档片段。") # 5. 创建索引并持久化 # 这里将文档分割、嵌入并存储到 Chroma index = VectorStoreIndex.from_documents( documents, storage_context=storage_context, show_progress=True ) # 索引本身的信息(如文档id映射)也可以持久化,但主要数据已在 Chroma 中 # index.storage_context.persist(persist_dir=persist_dir) print(f"向量索引已创建并保存至 {persist_dir}")运行这个脚本:
python rag_indexer.py如果成功,你会看到类似“已加载 X 个文档片段。”和“向量索引已创建并保存至 ./chroma_db”的输出。chroma_db目录下会生成数据库文件。
3.3 实现检索查询引擎
索引创建好后,我们需要一个查询引擎来检索答案。创建rag_query.py:
from llama_index.core import VectorStoreIndex from llama_index.vector_stores.chroma import ChromaVectorStore from llama_index.embeddings.ollama import OllamaEmbedding from llama_index.core import Settings import chromadb # 配置嵌入模型(必须与索引时一致) Settings.embed_model = OllamaEmbedding(model_name="nomic-embed-text") # 连接已存在的 Chroma 集合 persist_dir = "./chroma_db" chroma_client = chromadb.PersistentClient(path=persist_dir) chroma_collection = chroma_client.get_collection("tech_knowledge") vector_store = ChromaVectorStore(chroma_collection=chroma_collection) # 从向量存储加载索引 index = VectorStoreIndex.from_vector_store(vector_store=vector_store) # 创建查询引擎 # similarity_top_k 控制返回的上下文片段数量 # response_mode 设为 “compact” 可以优化上下文长度 query_engine = index.as_query_engine(similarity_top_k=2, response_mode="compact") # 进行查询 question = “FastAPI 的主要特性有哪些?” response = query_engine.query(question) print(f"问题:{question}") print(f"答案:{response.response}") print("\n--- 检索到的上下文 ---") for i, node in enumerate(response.source_nodes): print(f"[片段 {i+1}] {node.text[:200]}...") # 打印前200字符运行测试:
python rag_query.py你应该能看到模型基于我们提供的文档片段生成的答案,并附带了它参考的原文上下文。这证明了 RAG 系统正在工作:模型不是凭空编造,而是基于检索到的知识在回答。
4. 开发 Agent 与 Skills:让助手“动手”执行任务
现在,我们赋予助手行动能力。我们将创建一个 Agent,它除了能使用 RAG 知识库回答问题,还能调用两个自定义 Skill:一个用于生成代码片段,另一个用于将内容保存到文件。
4.1 定义自定义 Skills
在 LlamaIndex 中,Skill 通过FunctionTool来定义。创建skills.py:
import os from typing import Any from llama_index.core.tools import FunctionTool def generate_code(task_description: str, language: str = “python”) -> str: """ 根据任务描述生成指定编程语言的代码片段。 Args: task_description: 代码需要完成的任务的自然语言描述。 language: 目标编程语言,例如 ‘python‘, ’javascript‘, ’go‘。 Returns: 生成的代码字符串。 """ # 注意:这是一个简化实现。实际项目中,这里应该调用一个代码生成模型或 API。 # 此处为演示,我们返回一个模拟的代码字符串。 code_template = f“““# 根据任务‘{task_description}‘生成的 {language} 代码 # 请注意:这是模拟生成,实际应集成代码生成模型。 def mock_generated_function(): # TODO: 实现具体逻辑 print(‘Hello from generated code’) return None ””” return code_template def save_to_file(content: str, filepath: str) -> str: """ 将给定的文本内容保存到指定文件路径。 Args: content: 需要保存的文本内容。 filepath: 目标文件的路径(例如:’./output/result.py‘)。 Returns: 操作结果信息。 """ try: # 确保目录存在 os.makedirs(os.path.dirname(filepath), exist_ok=True) with open(filepath, ‘w’, encoding=‘utf-8’) as f: f.write(content) return f“内容已成功保存到 {filepath}” except Exception as e: return f“保存文件时出错:{str(e)}” # 将函数包装成 Agent 可用的 Tool code_gen_tool = FunctionTool.from_defaults( fn=generate_code, name=“generate_code”, description=“根据自然语言描述生成代码片段。需要提供任务描述和编程语言。” ) file_save_tool = FunctionTool.from_defaults( fn=save_to_file, name=“save_to_file”, description=“将文本内容保存到本地文件系统。需要提供内容和完整的文件路径。” ) # 导出工具列表 all_tools = [code_gen_tool, file_save_tool]4.2 创建集成 RAG 与 Skills 的 Agent
我们将创建一个 Agent,它首先尝试用 RAG 回答,如果问题涉及代码生成或文件操作,则调用相应的 Skill。创建agent_runner.py:
from llama_index.core.agent import ReActAgent from llama_index.llms.ollama import Ollama from skills import all_tools from rag_query import query_engine # 导入之前创建的 RAG 查询引擎 import logging # 设置日志,方便观察 Agent 的思考过程 logging.basicConfig(level=logging.INFO) # 1. 初始化 LLM(使用本地 Ollama 服务) llm = Ollama(model=“llama3.2”, request_timeout=60.0) # 2. 创建 Agent,并传入所有可用的工具(Skills) agent = ReActAgent.from_tools( tools=all_tools, llm=llm, verbose=True, # 打印 Agent 的推理步骤 max_iterations=10 # 限制最大迭代次数,防止死循环 ) def ask_assistant(question: str) -> str: """ 向助手提问。策略:先尝试用 RAG 回答纯知识问题, 若问题涉及工具调用(如’生成‘、’保存‘等关键词),则交给 Agent。 """ # 简单关键词判断,实际可用更复杂的分类器 tool_keywords = [“生成”, “写一个”, “创建”, “保存”, “写到文件”, “运行”, “执行”] is_tool_query = any(keyword in question for keyword in tool_keywords) if is_tool_query: print(“[模式] Agent 模式(工具调用)”) response = agent.chat(question) return str(response) else: print(“[模式] RAG 模式(知识问答)”) response = query_engine.query(question) # 可以在这里加入对 RAG 答案置信度的判断,如果置信度低,再转给 Agent 或通用 LLM return response.response # 交互式测试 if __name__ == “__main__”: print(“智能技术问答助手已启动(输入 ‘quit’ 退出)...”) while True: try: user_input = input(“\n您的问题:”).strip() if user_input.lower() in [‘quit’, ‘exit’, ‘q’]: break if not user_input: continue answer = ask_assistant(user_input) print(f“\n助手:{answer}”) except KeyboardInterrupt: break except Exception as e: print(f“处理请求时出错:{e}”)运行这个 Agent:
python agent_runner.py现在你可以进行测试:
- RAG 模式:问“FastAPI 的主要特性有哪些?”,它会从知识库检索并回答。
- Agent 模式:问“生成一个 Python 函数,用于计算斐波那契数列”,它会调用
generate_code工具。再问“将刚才生成的代码保存到./output/fib.py”,它会调用save_to_file工具。
观察控制台,当处于 Agent 模式时,verbose=True会打印出 ReAct 框架的思考过程(Thought:,Action:,Observation:),这有助于调试 Agent 的决策逻辑。
5. 进阶集成:通过 MCP 标准化 Skills 与探索 Hermes
5.1 将自定义 Skills 包装为 MCP 服务器
为了让我们的 Skills 能被更多支持 MCP 的客户端使用,我们可以将其包装成一个 MCP 服务器。创建一个简单的mcp_server.py:
# 注意:这是一个概念性示例,MCP 的实现细节可能随版本变化。 # 实际开发请参考官方 MCP SDK:https://github.com/modelcontextprotocol/servers import asyncio from mcp import Server, StdioServerTransport from mcp.types import Tool, TextContent # 复用之前的技能函数 from skills import generate_code, save_to_file async def main(): # 1. 定义 MCP 工具描述 tools = [ Tool( name=“generate_code”, description=“根据自然语言描述生成代码片段。”, inputSchema={ “type”: “object”, “properties”: { “task_description”: {“type”: “string”}, “language”: {“type”: “string”, “default”: “python”} }, “required”: [“task_description”] } ), Tool( name=“save_to_file”, description=“将文本内容保存到本地文件系统。”, inputSchema={ “type”: “object”, “properties”: { “content”: {“type”: “string”}, “filepath”: {“type”: “string”} }, “required”: [“content”, “filepath”] } ) ] # 2. 创建 Server 实例 server = Server(“tech-assistant-tools”) # 3. 注册工具列表 @server.list_tools() async def handle_list_tools(): return tools # 4. 注册工具调用处理函数 @server.call_tool() async def handle_call_tool(name: str, arguments: dict) -> list[TextContent]: if name == “generate_code”: result = generate_code( arguments.get(“task_description”), arguments.get(“language”, “python”) ) elif name == “save_to_file”: result = save_to_file( arguments.get(“content”), arguments.get(“filepath”) ) else: result = f“未知工具:{name}” return [TextContent(type=“text”, text=str(result))] # 5. 使用标准输入输出传输(便于与任何 MCP 客户端集成) transport = StdioServerTransport() async with server.run(transport): await asyncio.Future() # 永久运行 if __name__ == “__main__”: asyncio.run(main())运行此服务器后,任何兼容 MCP 的客户端(如 Claude Desktop、支持 MCP 的 IDE 插件)都可以发现并调用这些工具,实现了 Skills 的跨平台复用。
5.2 关于 Hermes Agent 与 Claude Skills
- Hermes Agent:通常指基于特定模型(如 Hermes-2)优化的 Agent 框架或实现。其官网可能提供专门的部署方式或配置。在我们的架构中,可以将 Ollama 的 LLM 替换为 Hermes 模型(如果可用),但 Agent 的逻辑层(ReAct)和工具层(MCP)可以保持不变。
- Claude Skills / Superpower Skills:这是 Claude 模型生态中的概念,类似于自定义指令或工具。Anthropic 的 Claude API 也支持类似 Function Calling 的工具调用。我们的 MCP 服务器同样可以作为一个 Skills 提供者,被 Claude 通过 MCP 协议调用。
核心思想是解耦:LLM(大脑)、规划框架(思维链)、工具协议(MCP)、具体工具实现彼此独立。这样,更换大脑(Llama, Claude, GPT)或前端(命令行、Web、IDE)时,核心的工具能力可以复用。
6. 生产环境考量、排错与最佳实践
将原型推进到可用的生产环境,需要关注稳定性、性能和可维护性。
6.1 常见问题排查表
| 问题现象 | 可能原因 | 检查点 | 解决方案 |
|---|---|---|---|
| Ollama 服务连接失败 | Ollama 未启动;端口被占用;网络问题。 | 运行ollama list查看服务状态;检查127.0.0.1:11434是否可达。 | 启动 Ollama 服务;重启电脑或检查防火墙。 |
| RAG 检索结果不相关 | 嵌入模型不匹配;文档分块策略不佳;检索 top_k 值太小。 | 确认索引和查询使用相同的嵌入模型;检查原始文档分块是否合理(大小、重叠)。 | 尝试不同的嵌入模型;调整文本分割器参数;增大similarity_top_k。 |
| Agent 陷入循环或调用错误工具 | 工具描述不清晰;LLM 理解有误;ReAct 迭代次数过多。 | 查看verbose=True的日志,观察Thought和Action。 | 优化工具的名称和描述,使其更精确;设置max_iterations(如 5);在 Prompt 中加入明确约束。 |
| 生成内容不符合预期(胡言乱语) | Prompt 指令不明确;模型能力不足;上下文过长或混乱。 | 检查发送给模型的完整 Prompt(开启框架的 debug 日志)。 | 优化系统 Prompt,明确角色、格式和限制;尝试更强大的模型;清理或压缩上下文。 |
| 文件操作权限错误 | 虚拟环境或脚本运行用户无写权限;路径不存在。 | 检查目标目录权限;确认os.makedirs是否成功。 | 确保项目目录有读写权限;在代码中做好异常捕获和日志记录。 |
6.2 性能与优化建议
- 嵌入模型选择:对于中文,可考虑
bge-m3、text2vec等。使用Ollama可以拉取对应的嵌入模型,如ollama pull bge-m3,并在代码中切换model_name。 - 向量数据库选型:对于生产环境,
Chroma适合轻量级应用。数据量大或要求高可用时,考虑Qdrant、Weaviate或Pinecone(云服务)。 - 检索优化:
- 重排序:在初步向量检索后,使用一个交叉编码器模型对结果进行精排,可以显著提升精度。LlamaIndex 支持集成
CohereRerank、BGERerank等。 - 混合检索:结合关键词检索(如 BM25)和向量检索,取长补短。
- 重排序:在初步向量检索后,使用一个交叉编码器模型对结果进行精排,可以显著提升精度。LlamaIndex 支持集成
- Agent 稳定性:
- 结构化输出:要求模型以 JSON 等固定格式返回,便于解析。
- 超时与重试:为工具调用和 LLM 请求设置超时和重试机制。
- 验证与过滤:对 Agent 生成的动作(如文件路径、系统命令)进行安全验证,防止越权操作。
6.3 安全注意事项
- 工具权限控制:像
save_to_file、execute_code这样的工具非常危险。必须在生产环境中实施严格的路径白名单、参数校验和权限隔离。绝对不要让 Agent 拥有直接执行任意 Shell 命令或访问系统关键文件的能力。 - Prompt 注入防护:用户输入可能包含恶意指令,试图让模型忽略之前的系统 Prompt。需要在拼接用户输入时进行适当的清洗和转义,并在系统 Prompt 中强调必须遵守指令。
- 数据隐私:使用本地模型(如 Ollama)和本地向量数据库是保护隐私的好方法。如果必须使用云 API,确保数据传输加密,并了解供应商的数据处理政策。
6.4 何时考虑微调?
微调是成本较高的操作。在以下场景可以考虑:
- 风格固化:需要模型输出严格遵循公司特定的代码风格、文档格式或邮件模板。
- 专业术语:领域术语(如特定医药、法律名词)在通用模型中表现不佳,且 RAG 难以完全解决。
- 复杂推理模式:任务需要一种固定的、多步骤的推理链条,而通过 Prompt 难以稳定引导。
使用LLaMA-Factory、Axolotl等工具可以简化微调流程。但请记住:先尽力优化 Prompt、RAG 和 Agent 设计,仍无法满足需求时,再评估微调的 ROI。
从 Prompt 工程到 RAG,再到 Agent 和 Skills,最后通过 MCP 实现标准化,这是一个构建复杂 LLM 应用的清晰路径。本项目提供了一个可运行的起点,但每个环节都有深化的空间:例如为 RAG 加入更智能的文档解析和重排序,为 Agent 设计更复杂的规划逻辑,或者开发一整套企业级的安全工具。
最关键的是理解数据流和控制流:用户输入如何被分类,是走 RAG 查询还是 Agent 规划?Agent 的思考过程如何被记录和监控?工具的执行结果如何反馈并影响后续决策?把这些流程梳理清楚,并用代码实现出来,你就掌握了构建 LLM 应用的核心工程能力。接下来,你可以尝试将 Agent 接入 Web 服务(如 FastAPI),为其添加记忆功能,或者集成更强大的外部工具(如搜索引擎、数据库),让它真正成为一个有用的生产力工具。