公司动态

AI应用开发实战:大模型、RAG与Agent核心工程链路

📅 2026/8/31 3:58:40
AI应用开发实战:大模型、RAG与Agent核心工程链路
过去一年技术社区里讨论 AI 的方式发生了明显变化。前年大家还在争论大模型的能力边界去年开始研究提示词怎么写到了今年越来越多的团队已经不再满足于“能跑通 Demo”而是把 AI 当作基础设施接到业务流程中。作为长期参与 AI 应用落地的人我能明显感觉到真正的拐点不是某个模型参数的跃升而是 AI 工程化能力的成熟。模型开始像数据库、消息队列一样成为业务系统里一个可以被设计、被观测、被运维的组件。本文不打算做空泛的趋势判断而是围绕 AI 应用开发这条主线梳理拐点背后的技术变化并给出一套完整可运行的最小工程示例包含大模型接入、RAG 检索增强问答和 Agent 工具调用三个核心模块。无论你是刚开始接触 AI 开发还是已经在做项目重构这篇文章都能提供一套可以直接上手的思路。1. 背景与核心概念1.1 为什么说拐点已至判断一项技术是否到了拐点不是看发布会上的演示有多惊艳而是看它是否开始进入软件工程的“常规组件清单”。2025 年之后AI 应用开发的节奏明显加快了背后的信号有三个。第一个信号是模型能力的商品化。对话模型、向量模型、多模态模型都变成了可以通过标准化接口调用的服务团队不再需要从零训练模型而是把模型当作能力底座把精力放在业务设计上。第二个信号是开发框架逐渐稳定。过去一年里围绕大模型的开发范式沉淀出了几个高度一致的模式提示词管理、上下文组装、工具调用、结果评测。这些模式正在被封装成框架和平台能力普通开发者不需要自己造轮子。第三个信号是评测意识被普遍接受。再也不是“感觉回答得不错”就算完成而是用测试集、指标和回归机制来度量 AI 应用的质量。这三个信号对开发者的影响非常直接。过去决定 AI 应用质量的是模型本身今天决定质量的更多是工程链路数据怎么组织、提示词怎么管理、检索怎么做、工具调用怎么兜底、效果怎么评测。这条链路就是 AI 工程实践要解决的核心问题。1.2 三个绕不开的技术概念在 AI 应用开发中有三个概念出现的频率最高大语言模型、RAG、Agent。很多讨论把三者混在一起实际上它们解决的是不同层面的问题。大语言模型是推理和生成的基础能力负责理解用户的输入并生成文本。它像一个“能力内核”但它本身不掌握企业私有数据也无法访问外部系统。RAG 全称 Retrieval-Augmented Generation也就是检索增强生成核心思路是在模型生成之前先从外部知识库中检索与问题相关的内容把检索结果和问题一起交给模型让模型基于这些材料来回答。这种方式能显著减少模型胡编乱造的概率是知识库问答类应用的主流方案。Agent 强调的是任务规划与工具调用。模型不只是在对话而是在理解任务后决定调用哪些外部工具比如查天气、查日历、操作数据库最后把工具结果整合成答案。概念核心能力典型场景大语言模型文本理解、推理、生成对话、写作、代码生成RAG外部知识检索 生成企业知识库问答、文档助手Agent任务规划、工具调用、结果决策智能客服、自动化办公、数据分析1.3 拐点背后的核心技术变化如果我们再往下拆一层会发现拐点背后其实是应用架构的转变。以前的 AI 应用大多是单次调用用户输入一句话模型返回一句话。现在的主流应用变成了多阶段的流水线先做意图识别再检索数据再组装上下文再调用模型最后可能还要执行动作并校验结果。这种架构转变带来了新的设计话题比如上下文工程。模型能接收的输入长度有限如何把最相关的信息放进上下文、如何控制上下文规模、如何设计系统提示词逐渐成为 AI 开发的核心技能。与此同时AI 编程工具也改变了开发者的工作方式Cursor 这类 AI 编程工具已经能完成大量重复性编码工作但前提是开发者自己能设计清楚模块边界和数据结构。工具越强大对开发者工程能力的要求反而越高。2. AI 应用开发的关键技术栈2.1 大模型接入的三种方式选择怎么接入大模型是 AI 应用开发的第一步。目前常见的方式有三种。第一种是使用云厂商的模型 API。这种方式接入最快模型能力通常最强按调用量计费适合快速验证业务想法和中小规模应用。第二种是本地部署开源模型。越来越多的开源模型已经具备了相当强的对话和工具调用能力结合 Ollama、vLLM 等工具团队可以在自己的服务器上运行模型数据不出内网长期成本更可控特别适合数据敏感的业务。第三种是混合部署。把轻量任务交给本地小模型把复杂推理交给云端大模型兼顾成本、延迟和效果。这里重点说本地部署。对很多开发者来说用 Ollama 搭建一个本地推理环境是最快的上手路径。Ollama 本身就是一个模型运行时它提供 OpenAI 兼容接口意味着我们不需要修改业务代码只要把接口地址指向本地服务就能在各种项目里复用同一套调用逻辑。这也是本文章节中要演示的方式。2.2 从 Prompt 到 Agent 的演进最早的大模型应用开发核心就是写提示词。把任务描述清楚把示例放进去模型就能按预期工作。但随着业务复杂化纯提示词方案暴露出两个痛点一是模型只具备“嘴”的能力无法执行动作二是面对多步骤任务时一次提示词往往覆盖不了完整的流程需求。于是出现了 Function Calling也就是函数调用。模型在生成回复之前会先判断“需要调用哪个函数、传入什么参数”然后由代码真正执行函数再把结果回传给模型由模型整合输出。在此基础上Agent 的概念被逐渐放大一个流程里可以有很多个函数模型自主决定调用顺序。我曾经在一个办公自动化项目里用这个模式实现了“查询库存—生成采购建议—写入审批表”的完整链路效果比固定流程脚本灵活很多。2.3 RAG 检索增强生成RAG 解决的是“模型不知道”和“模型瞎编”两个问题。模型的知识截止于训练数据企业内部的新文档、实时数据它都看不到RAG 先用检索把相关资料找出来让模型基于资料回答。标准 RAG 流程可以拆成四个步骤。第一步是文档切分把长文档切成适合检索的片段。第二步是向量化用 Embedding 模型把每个片段转成向量。第三步是检索把用户问题也转成向量用余弦相似度找到最相关的片段。第四步是生成把检索到的片段和用户问题一起交给模型。想做好 RAG切分策略和检索质量比模型本身更关键这也是后面实战部分要演示的重点。3. 环境准备与版本说明3.1 开发环境清单在开始写代码之前先准备一套可复现的运行环境。不同机器的软件版本可能有差异本文以常见环境为例重点演示配置思路具体版本需要根据你的项目实际情况调整。组件用途说明Python 3.10运行示例代码推荐使用 pyenv 或 Anaconda 管理虚拟环境Ollama本地大模型运行时支持 Linux / macOS / WindowsDocker可选容器化部署服务器部署更推荐VS Code 或 Cursor开发工具建议安装 Python 插件和 AI 辅助插件3.2 安装本地模型运行时先在本地安装 Ollama。Linux 和 macOS 可以使用官方安装脚本curl -fsSL https://ollama.com/install.sh | shWindows 用户直接前往 Ollama 官网下载安装包。如果你的服务器上已经装了 Docker也可以用容器方式运行docker run -d -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama安装完成后拉取两个模型。一个是对话模型本文示例使用 Qwen2.5 7B另一个是向量模型用于 RAG 的文本向量化# 拉取对话模型 ollama pull qwen2.5:7b # 拉取向量模型 ollama pull bge-m3 # 查看已安装模型 ollama list拉取完成后执行ollama serve启动服务。Ollama 默认监听 11434 端口并提供 OpenAI 兼容的接口地址http://localhost:11434/v1。你可以先用一句话验证模型是否正常工作ollama run qwen2.5:7b 你好请简单介绍你自己3.3 创建项目结构为了让示例清晰可复制我们使用扁平结构一个目录就是一个完整的后端服务ai-assistant-demo/ ├── main.py # FastAPI 服务入口 ├── llm_client.py # 大模型对话模块 ├── rag_engine.py # RAG 检索模块 ├── agent.py # Agent 工具调用模块 ├── requirements.txt # Python 依赖 └── README.md # 项目说明三个业务模块互相独立方便你单独抽取复用。4. 完整实战构建一个最小 AI 助手服务4.1 添加依赖先创建requirements.txt包含 Web 框架和 OpenAI 客户端库。因为 Ollama 暴露的是 OpenAI 兼容接口所以我们直接复用 OpenAI 官方 Python SDK不需要额外适配。# 文件路径ai-assistant-demo/requirements.txt fastapi uvicorn openai pydantic安装依赖pip install -r requirements.txt建议创建独立的 Python 虚拟环境避免污染全局环境。4.2 编写大模型调用模块llm_client.py是整条链路的基础模块。它封装了对话接口其他模块通过调用chat()函数来获取模型回复。关键点在于我们通过环境变量把接口地址、模型名和密钥全部配置化这样代码既可以在本地 Ollama 上运行也可以切换到云端模型服务。# 文件路径ai-assistant-demo/llm_client.py import os from openai import OpenAI BASE_URL os.getenv(BASE_URL, http://localhost:11434/v1) API_KEY os.getenv(API_KEY, ollama) MODEL os.getenv(MODEL_NAME, qwen2.5:7b) client OpenAI(base_urlBASE_URL, api_keyAPI_KEY) def chat(prompt: str, system_prompt: str 你是一个乐于助人的 AI 助手。) - str: 调用 OpenAI 兼容接口完成一次对话。 resp client.chat.completions.create( modelMODEL, messages[ {role: system, content: system_prompt}, {role: user, content: prompt}, ], temperature0.7, ) return resp.choices[0].message.content这里需要解释两个参数。BASE_URL指向 Ollama 的兼容接口API_KEY在本地场景下可以填任意占位值因为 Ollama 不做身份校验。MODEL必须和本地已经拉取的模型一致否则会报model not found错误。4.3 实现 RAG 检索增强问答rag_engine.py实现了一个最小可用的内存版 RAG。它先把文档列表向量化收到查询时计算余弦相似度返回最相关的片段。这个版本没有引入向量数据库是为了让原理更直观正式项目可以用 Chroma、FAISS 或 Milvus 替换存储层业务代码基本不用改。# 文件路径ai-assistant-demo/rag_engine.py import os from openai import OpenAI BASE_URL os.getenv(BASE_URL, http://localhost:11434/v1) API_KEY os.getenv(API_KEY, ollama) EMBEDDING_MODEL os.getenv(EMBEDDING_MODEL, bge-m3) client OpenAI(base_urlBASE_URL, api_keyAPI_KEY) _doc_embeddings [] def build_index(doc_list: list) - None: 把文档列表转成内存向量索引。 正式项目中建议使用向量数据库存储 这里用列表存储是为了让示例足够简单、易于理解。 global _doc_embeddings _doc_embeddings [] for text in doc_list: vec _embed(text) _doc_embeddings.append({text: text, vector: vec}) def retrieve(query: str, top_k: int 3) - list: 计算 query 与所有文档的余弦相似度返回 top_k 条最相关内容。 if not _doc_embeddings: return [] q_vec _embed(query) scored [] for item in _doc_embeddings: sim _cosine(q_vec, item[vector]) scored.append((sim, item[text])) scored.sort(keylambda x: x[0], reverseTrue) return [text for _, text in scored[:top_k]] def _embed(text: str) - list: resp client.embeddings.create(modelEMBEDDING_MODEL, inputtext) return resp.data[0].embedding def _cosine(a: list, b: list) - float: dot sum(x * y for x, y in zip(a, b)) na sum(x * x for x in a) ** 0.5 nb sum(x * x for x in b) ** 0.5 if na 0 or nb 0: return 0.0 return dot / (na * nb)注意retrieve()返回的是原始材料真正组织提示词并调用模型生成答案的逻辑放在服务入口层处理。这样检索和生成解耦后面换数据库或换模型都很方便。4.4 实现 Agent 工具调用agent.py演示了 Agent 最常见的实现方式把工具列表交给模型模型自主判断调用哪些函数代码执行函数后用结果继续对话。示例中提供了两个工具一个是查询天气一个是获取当前时间。# 文件路径ai-assistant-demo/agent.py import datetime import json import os from openai import OpenAI BASE_URL os.getenv(BASE_URL, http://localhost:11434/v1) API_KEY os.getenv(API_KEY, ollama) MODEL os.getenv(MODEL_NAME, qwen2.5:7b) client OpenAI(base_urlBASE_URL, api_keyAPI_KEY) TOOLS [ { type: function, function: { name: get_weather, description: 获取指定城市的天气信息示例数据, parameters: { type: object, properties: { city: {type: string, description: 城市名称例如北京} }, required: [city], }, }, }, { type: function, function: { name: get_current_time, description: 获取当前时间, parameters: {type: object, properties: {}}, }, }, ] def get_weather(city: str) - str: 模拟天气查询真实项目请替换为第三方天气 API。 return json.dumps( {city: city, weather: 晴, temperature: 25}, ensure_asciiFalse, ) def get_current_time() - str: return datetime.datetime.now().strftime(%Y-%m-%d %H:%M:%S) def run_agent(user_message: str) - str: 让模型自主决定是否调用工具循环直到得到最终答案。 messages [{role: user, content: user_message}] for _ in range(5): resp client.chat.completions.create( modelMODEL, messagesmessages, toolsTOOLS, tool_choiceauto, ) msg resp.choices[0].message if not msg.tool_calls: return msg.content or messages.append(msg) for tc in msg.tool_calls: fn_name tc.function.name args json.loads(tc.function.arguments or {}) if fn_name get_weather: result get_weather(args.get(city, )) elif fn_name get_current_time: result get_current_time() else: result json.dumps({error: unknown tool}) messages.append( { role: tool, tool_call_id: tc.id, content: result, } ) return 工具调用次数超过上限请简化问题后再试。这个循环是 Agent 的核心机制模型返回tool_calls说明它想调用工具代码执行后把结果以role: tool的消息追加进对话模型再基于最新的完整上下文继续推理。循环次数限制是必要的否则遇到复杂问题时可能陷入无限调用。4.5 启动服务与验证最后用 FastAPI 把三个模块串成一个 HTTP 服务。我使用lifespan机制在服务启动时初始化 RAG 索引这样请求到达时检索数据已经就绪。# 文件路径ai-assistant-demo/main.py from contextlib import asynccontextmanager from fastapi import FastAPI from pydantic import BaseModel from agent import run_agent from llm_client import chat from rag_engine import build_index, retrieve asynccontextmanager async def lifespan(app: FastAPI): # 启动时构建内存索引方便示例直接演示 RAG build_index( [ AI Agent 是一种能够感知环境、做出决策并执行动作的智能体程序。, RAG检索增强生成在生成前先从外部知识库检索相关内容降低模型幻觉。, 本地部署大模型通常使用 Ollama 或 vLLM通过 OpenAI 兼容接口对外提供服务。, ] ) yield app FastAPI(titleAI Assistant Demo, lifespanlifespan) class ChatRequest(BaseModel): message: str use_rag: bool False class ChatResponse(BaseModel): reply: str references: list [] app.post(/chat) def chat_api(req: ChatRequest): if req.use_rag: docs retrieve(req.message, top_k3) context \n.join(docs) prompt f请基于以下资料回答问题\n\n{context}\n\n问题{req.message} reply chat(prompt) return ChatResponse(replyreply, referencesdocs) reply chat(req.message) return ChatResponse(replyreply) app.post(/agent) def agent_api(req: ChatRequest): reply run_agent(req.message) return ChatResponse(replyreply)启动服务uvicorn main:app --reload --port 8000然后打开一个新的终端窗口验证接口。先测普通对话curl -X POST http://localhost:8000/chat \ -H Content-Type: application/json \ -d {message: 你好请介绍一下你自己}再测试 RAG 增强对话curl -X POST http://localhost:8000/chat \ -H Content-Type: application/json \ -d {message: RAG 能解决什么问题, use_rag: true}最后测试 Agent 工具调用curl -X POST http://localhost:8000/agent \ -H Content-Type: application/json \ -d {message: 现在几点了}如果一切正常你会看到模型分别返回自我介绍、基于 RAG 资料生成的回答以及通过工具获取的实时时间。到这里一个同时具备对话、检索增强和工具调用能力的 AI 助手后端就完整跑通了。5. 常见问题与排查思路AI 应用开发中报错和异常几乎不可避免。很多问题看起来五花八门但根因往往集中在少数几个环节。下面按排查顺序整理了一张速查表。问题现象常见原因排查与解决思路Connection refusedOllama 服务未启动先执行ollama serve确认 11434 端口可访问model not found模型尚未拉取到本地ollama pull qwen2.5:7b再ollama list确认首次请求非常慢模型冷启动加载到内存提前用ollama run qwen2.5:7b hi做预热回答被截断未显式配置max_tokens在create方法中设置max_tokens2048显存不足 OOM模型参数量超过显卡容量换小参数模型或使用 4bit 量化版本工具调用不生效模型本身不支持 function calling查看模型文档确认是否支持 tools 参数检索结果不相关文档切分粒度过大或过小调整 chunk 大小和重叠窗口必要时加重排中文乱码终端编码问题Windows 下先执行chcp 65001除了表格里的问题还有两个高频场景需要单独强调。第一个是本地模型和向量模型的版本匹配。Embedding 模型的输出维度可能不同如果在代码里切换了模型但没清空索引会出现维度不一致的报错。遇到这种情况重启服务重新构建索引即可。第二个是 Agent 循环失控。虽然示例里限制了 5 次循环但真实业务中工具输入参数可能来自用户输入需要做参数校验和结果平滑处理避免把异常结果直接回传给模型。6. AI 工程化的最佳实践6.1 用工程思维管理提示词很多团队把提示词写在代码里维护起来很痛苦改一句话要重新发版。更好的做法是把提示词当作配置资产管理系统提示词、少样本示例、输出格式说明全部放配置文件用版本控制追踪变更。业务提示词变化频繁应该允许运营人员在高权限管理界面中调整涉及模型行为的核心提示词则要经过评审再发布。提示词不只是“写得好不好”的问题还是可维护性和团队协作的问题。6.2 建立评测与回归机制AI 应用的输出天然带有随机性没有评测机制就无法控制质量。建议从第一天就建立最小评测集哪怕只有二十条典型问题。每次修改提示词、换模型、调参数都跑一遍评测集观察回答是否退化。评测指标可以采用定性打分和定量指标结合的方式定量指标包括回答准确率、格式合规率、关键字命中率等。这说起来简单但很多团队因为怕麻烦而跳过结果上线后出现各种概率性错误排查成本比写评测集高得多。6.3 安全与合规边界AI 应用涉及的安全问题比传统后端更复杂。首要是输入侧的控制对用户输入做敏感信息检测和长度限制防止提示词注入。然后是权限隔离涉及工具调用时必须遵循最小权限原则模型能调用的工具应该只限定在业务必要范围内工具函数内部要对入参做校验不能直接把数据库连接或文件系统暴露给模型。最后是输出侧的校验尤其是生成 SQL、代码或 HTML 的场景必须对输出内容做二次检查。这里要特别提示涉及生产环境的数据变更操作必须经过审批在测试环境