十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从Demo到生产:大模型应用RAG、Agent与推理优化实战

从Demo到生产:大模型应用RAG、Agent与推理优化实战 最近科技圈有一条消息值得关注某家头部大模型创业公司否认了 IPO 传闻但市场上关于“上市窗口期”的讨论并没有停止。作为技术人员我们通常不太关注资本层面的博弈更关心的是如果大模型公司真的要走向资本市场它的技术底座是否撑得起更高的估值预期换句话说当产品体验、用户规模、营收数据都要被拿出来“体检”时技术团队靠什么交出答卷这篇文章不讨论股价预测也不做投资建议而是从工程化视角拆解 AI 大模型公司的技术竞争力。我们会围绕大模型应用开发中最核心的三块技术——长文本与 RAG、Agent 与 Function Calling、推理性能与成本优化——展开完整实战并给出从 Demo 到生产环境的落地建议。无论你是后端开发者、算法工程师还是正打算进入 AI 应用赛道的技术人这篇内容都值得收藏慢慢看。1. 背景上市窗口期对 AI 公司意味着什么1.1 从“否认 IPO”看市场对大模型公司的关注点过去一两年大模型赛道经历了从技术引爆到资本狂欢再到冷静审视的阶段。市场对 AI 公司的评价标准已经从“谁的模型分数高”逐步转向“谁的产品能规模化赚钱”。一家公司即使拥有不错的基座模型如果无法在推理成本、响应速度、稳定性和安全性上达到商业化要求那么它的增长故事就很难讲下去。所谓“上市窗口期”本质上是市场对公司的综合体检期。财务数据只是结果过程指标才是决定结果的原因。对技术人来说过程指标包括模型调用延迟和吞吐量是否满足用户体验长文本场景下的检索准确率是否稳定Agent 任务的成功率和可观测性是否达到企业级要求系统能否支撑流量突增而不会成本失控这些问题每一个都能在技术栈里找到对应的答案。1.2 窗口期到来之前技术团队需要补哪些课如果说创业初期比拼的是模型能力那么进入窗口期后比拼的就是工程化能力。模型能力决定上限工程化能力决定下限。工程化能力通常包含四个层面层面关注点常见技术基础设施层算力调度、GPU 利用率、模型推理框架vLLM、TensorRT-LLM、Kubernetes数据与检索层知识库构建、向量检索、召回质量Milvus、FAISS、Elasticsearch应用与编排层Agent 流程、工具调用、状态管理LangChain、Dify、自研编排引擎可观测与安全层日志、链路、评估、过滤、审计Prometheus、Grafana、LLM Guard一个成熟的 AI 应用团队应该在这四个层面都有沉淀。下面我们逐个展开。1.3 本文的讨论范围本文不写模型训练细节重点放在大模型应用工程化。我们需要掌握的核心内容包括长文本场景下的 RAG检索增强生成实战Agent 应用中 Function Calling 的设计与实现推理性能优化与成本控制的常见手段AI 应用从 Demo 到生产环境必须补齐的能力。每一部分都会给出可运行的示例代码和排查思路方便你在自己的项目里直接参考。2. 大模型公司的技术版图从训练到交付的全链路2.1 大模型应用的基本架构先看一张整体架构图不需要太复杂重点是厘清技术组件之间的关系用户请求 ↓ 接入层API Gateway / Web 应用 ↓ 应用编排层Agent、RAG 流程、业务逻辑 ↓ 模型服务层大模型 API / 私有化推理服务 ↓ 数据层向量库、业务数据库、缓存在实际项目中每一层都有自己的技术挑战。接入层关注鉴权和限流编排层关注任务拆解和状态管理模型服务层关注延迟和成本数据层关注召回质量和一致性。2.2 技术层拆解模型层、中间层、应用层我们可以进一步把大模型应用技术栈分为三层理解模型层包括基座模型的选择与部署。可以使用商用 API也可以基于开源模型私有化部署。不同选择会直接影响成本、数据隐私和延迟指标。中间层这是最容易被忽视、但最体现工程能力的一层。包括检索服务、工具调用、记忆管理、提示词模板、缓存策略等。中间层越健壮上层应用就能越快地开发新功能。应用层面向最终用户的产品功能比如智能客服、文档问答、代码助手、数据分析助手等。应用层通常只需要调用中间层提供的服务不需要关心底层模型细节。对于一家准备走向资本市场的 AI 公司来说中间层的沉淀往往是最重要的资产。因为模型可以替换但经过大量业务打磨的中间层能力无法轻易复制。2.3 工程化能力才是窗口期的核心变量为什么工程化能力会成为窗口期的核心变量原因是资本市场越来越看重增长的可复制性。假设一个智能客服项目在演示环境下表现很好但如果用户量从 1000 增长到 100 万系统还能不能稳定运行每次请求的边际成本能不能降到可接受范围答案不在模型里而在工程化体系里。所以在后续章节里我会重点讲清楚每一块技术到底怎么落地以及落地过程中最常见的坑是什么。3. 关键技术一长文本与 RAG 检索增强生成3.1 长文本处理为什么是大模型产品的核心竞争力知名的长文本处理能力让 Kimi 这类产品快速进入大众视野。对普通用户来说“能一次性读完一本小说并回答问题”是直观体验对企业用户来说“能分析一份几十页的合同并给出风险提示”才是真正创造价值的地方。但大模型的上下文窗口终究有上限并且窗口越长计算成本和响应延迟越高。更现实的做法不是把所有内容都塞进上下文而是先通过检索找到与问题最相关的片段再把片段交给模型回答。这就是 RAGRetrieval-Augmented Generation的核心思想。RAG 的价值可以概括为突破了上下文窗口限制可以随时更新知识不用重训练模型可以引用来源降低幻觉风险支持接入企业内部私有数据。3.2 RAG 架构拆解一个标准的 RAG 流程包含五个步骤文档解析将 PDF、Word、Markdown 等格式转换为纯文本。文本切分把长文档按固定长度或语义边界切分成 chunk。向量化用 Embedding 模型将 chunk 转换为向量。向量存储把向量写入向量数据库同时保存原始文本元数据。检索与生成用户提问时把问题向量化在向量库中检索最相似的 chunk拼接到 Prompt 中交给大模型回答。下面通过一个完整的 Python 示例来演示 RAG 服务的实现。3.3 代码实战基于向量数据库实现 RAG 检索服务我们使用 FastAPI ChromaDB OpenAI 兼容接口构建一个最小可运行的 RAG 服务。版本信息以你的实际环境为准这里重点展示设计思路。项目结构如下rag-service/ ├── app.py # FastAPI 入口 ├── ingest.py # 文档入库脚本 ├── requirements.txt # 依赖列表 └── data/ └── sample.txt # 示例知识文档先创建依赖文件requirements.txtfastapi uvicorn chromadb openai python-dotenv接下来写文档入库脚本。这个脚本负责读取本地文档切分成块然后写入向量数据库。# 文件路径rag-service/ingest.py import os from dotenv import load_dotenv import chromadb from chromadb.utils import embedding_functions load_dotenv() # 使用 OpenAI 兼容的 Embedding 接口 # 如果你的模型服务支持 OpenAI 格式直接替换 api_base 和 api_key OPENAI_API_KEY os.getenv(OPENAI_API_KEY, your-api-key) OPENAI_API_BASE os.getenv(OPENAI_API_BASE, https://api.openai.com/v1) class EmbeddingFunction: def __init__(self): self.client OpenAI(api_keyOPENAI_API_KEY, base_urlOPENAI_API_BASE) def embed_documents(self, texts): resp self.client.embeddings.create( modeltext-embedding-3-small, inputtexts ) return [item.embedding for item in resp.data] def embed_query(self, query): resp self.client.embeddings.create( modeltext-embedding-3-small, inputquery ) return resp.data[0].embedding # 初始化 Chroma 客户端 client chromadb.PersistentClient(path./chroma_data) collection client.get_or_create_collection( nameknowledge_base, embedding_functionEmbeddingFunctionV2(), metadata{hnsw:space: cosine} ) def load_document(file_path: str): 读取文本文件按固定长度切分 with open(file_path, r, encodingutf-8) as f: content f.read() # 简单切分每 500 个字符为一块重叠 50 字符 chunk_size 500 overlap 50 chunks [] start 0 while start len(content): end start chunk_size chunks.append(content[start:end]) if end len(content): break start end - overlap return chunks if __name__ __main__: chunks load_document(data/sample.txt) ids [fchunk-{i} for i in range(len(chunks))] metadatas [{source: sample.txt, index: i} for i in range(len(chunks))] collection.upsert( idsids, documentschunks, metadatasmetadatas ) print(f成功写入 {len(chunks)} 个文本块到向量数据库)注意上面代码里我引用了OpenAI需要补一行from openai import OpenAI。同时如果 ChromaDB 的embedding_functions不够灵活也可以直接传已经计算好的向量避免绑定某家 Embedding 服务。然后是 FastAPI 接口提供检索问答能力# 文件路径rag-service/app.py import os from fastapi import FastAPI from pydantic import BaseModel from openai import OpenAI import chromadb app FastAPI(titleRAG Service) OPENAI_API_KEY os.getenv(OPENAI_API_KEY, your-api-key) OPENAI_API_BASE os.getenv(OPENAI_API_BASE, https://api.openai.com/v1) client OpenAI(api_keyOPENAI_API_KEY, base_urlOPENAI_API_BASE) chroma_client chromadb.PersistentClient(path./chroma_data) collection chroma_client.get_or_create_collection(nameknowledge_base) class QueryRequest(BaseModel): question: str top_k: int 3 def retrieve(question: str, top_k: int 3): 向量检索 q_embedding client.embeddings.create( modeltext-embedding-3-small, inputquestion ).data[0].embedding results collection.query( query_embeddings[q_embedding], n_resultstop_k ) docs results.get(documents, [[]])[0] return docs def build_prompt(question: str, contexts: list[str]) - str: 组装 Prompt context_text \n\n.join([f[文档{i1}]\n{doc} for i, doc in enumerate(contexts)]) prompt f请根据以下参考文档回答问题。如果你从文档中找不到答案请如实说明不要编造。 参考文档 {context_text} 问题{question} 回答 return prompt app.post(/chat) def chat(req: QueryRequest): docs retrieve(req.question, req.top_k) if not docs: return {answer: 未检索到相关知识请换一个问法试试。, sources: []} prompt build_prompt(req.question, docs) resp client.chat.completions.create( modelgpt-4o-mini, messages[{role: user, content: prompt}], temperature0.2 ) return { answer: resp.choices[0].message.content, sources: docs } if __name__ __main__: import uvicorn uvicorn.run(app, host0.0.0.0, port8000)启动命令cd rag-service pip install -r requirements.txt python ingest.py uvicorn app:app --host 0.0.0.0 --port 8000调用接口curl -X POST http://localhost:8000/chat \ -H Content-Type: application/json \ -d {question: 这份文档里提到了哪些关键结论, top_k: 3}这就是一个完整的 RAG 最小闭环。注意实际生产中还需要处理 PDF 解析、OCR、文档更新、权限过滤等问题但整体架构是一致的。3.4 参数与效果调优RAG 的效果好坏很大程度上决定了大模型产品在企业场景中的可用性。影响最大的几个参数如下chunk 大小块太小语义不完整块太大检索噪声增多。建议从 300800 字符开始尝试。检索数量 top_k太少可能漏信息太多会稀释模型注意力。一般取值 35。重排序Rerank单纯靠向量相似度召回有时会把语义相近但不相关的文本排在前面。引入 cross-encoder 重排序模型可以有效提升准确率。Embedding 模型选择中文场景下建议优先选择对中文支持较好的模型并做小规模评测。一个常用的调优思路是构建一批业务真实问题人工标注标准答案然后用召回准确率和最终回答质量两个指标持续对比实验。4. 关键技术二Agent 与 Function Calling4.1 Agent 是大模型商业化的重要形态如果说 RAG 解决的是“让模型知道更多知识”的问题那么 Agent 解决的是“让模型能做更多事”的问题。用户不再满足于“问答”而是希望 AI 能自动完成一系列操作比如查询订单、修改排班、发送邮件、生成报表。这就必须让模型学会调用外部工具。在 OpenAI 兼容接口中Function Calling 是标准能力模型根据用户请求从预设函数列表中选择需要调用的函数并生成参数 JSON应用层负责真正执行函数再把执行结果返回给模型模型据此生成最终回复。4.2 Function Calling 的工作机制整个调用链路可以拆成四步应用在请求中声明可用的函数列表名称、描述、参数结构。模型根据用户意图选择函数输出结构化调用参数。应用执行函数拿到真实结果。应用把结果以消息形式返回给模型模型生成自然语言回复。这个设计的关键点在于模型只负责“决定调用谁”不负责“真正执行”。真正执行由应用层完成这样可以避免模型直接操作外部系统带来的安全和幻觉风险。4.3 代码实战用 Python 实现一个可执行工具的 Agent下面用一个天气查询 Agent 为例实现完整的 Function Calling 流程。# 文件路径agent_demo.py import json from openai import OpenAI client OpenAI() # 通过环境变量配置 api_key # 定义工具函数 def get_weather(city: str): 模拟天气查询接口 weather_data { 北京: 晴25°C, 上海: 多云28°C, 广州: 小雨26°C } return weather_data.get(city, 暂不支持该城市的天气查询) # 定义函数蓝图传给模型 tools [ { type: function, function: { name: get_weather, description: 查询指定城市的实时天气, parameters: { type: object, properties: { city: { type: string, description: 城市名称比如北京、上海 } }, required: [city] } } } ] def run_agent(user_message: str): messages [ {role: system, content: 你是一个天气助手。需要查询天气时请调用天气接口。}, {role: user, content: user_message} ] # 第一轮请求让模型决定是否调用工具 response client.chat.completions.create( modelgpt-4o-mini, messagesmessages, toolstools, tool_choiceauto ) msg response.choices[0].message messages.append(msg) # 如果模型决定调用工具 if msg.tool_calls: for tool_call in msg.tool_calls: fn_name tool_call.function.name fn_args json.loads(tool_call.function.arguments) print(f调用工具: {fn_name}, 参数: {fn_args}) if fn_name get_weather: result get_weather(**fn_args) else: result 未知工具 messages.append({ role: tool, tool_call_id: tool_call.id, content: str(result) }) # 第二轮请求让模型基于工具结果生成最终回答 second_response client.chat.completions.create( modelgpt-4o-mini, messagesmessages, toolstools ) return second_response.choices[0].message.content return msg.content if __name__ __main__: print(run_agent(今天北京天气怎么样))运行结果会类似调用工具: get_weather, 参数: {city: 北京} 北京今天晴25°C。这段代码虽然简单但已经涵盖了 Agent 最核心的模式工具声明、模型决策、应用执行、结果回填。4.4 Agent 设计中的常见坑在实际项目中Agent 的复杂度会高很多常见的坑包括工具描述不清晰模型无法准确判断该调用哪个工具导致调用错误。描述要写清楚“什么场景使用、参数含义、边界条件”。参数校验不足模型生成的参数可能不完整或类型错误应用层必须做二次校验。循环调用模型在拿到工具结果后可能会反复触发同一个工具形成死循环。需要设置最大迭代次数。缺少人工确认对于下单、删除、转账等敏感操作必须加入人工确认环节。可观测性不足每一步的思考过程、工具参数、返回结果都要有日志记录否则出了问题根本无法排查。对 Agent 应用来说稳定性比炫酷更重要。一个能稳定完成简单任务的小 Agent好过一个偶尔惊艳但经常失控的复杂 Agent。5. 关键技术三推理性能与成本控制5.1 为什么推理性能决定商业化的天花板大模型应用的商业模式本质上是将一次推理的边际成本与用户价值做匹配。如果每次请求都要消耗大量 GPU 时间那么用户规模越大亏损越严重增长反而变成负担。所以推理性能优化不是为了炫技而是为了让商业模型成立。5.2 常见推理优化手段推理优化分为模型侧和系统侧。模型侧优化量化Quantization把模型权重从 FP16 压缩到 INT8 或 INT4减少显存占用提升推理速度。模型蒸馏用小模型学习大模型的能力在效果损失可控的前提下降低单次推理成本。架构裁剪移除冗余层或注意力头减小模型规模。系统侧优化vLLM 等推理框架通过 PagedAttention 和 Continuous Batching 大幅提升吞吐量是目前开源社区最常用的方案。KV Cache 复用对前缀相同的请求复用 Key-Value 缓存可以显著减少重复计算。语义缓存对完全相同的业务问题直接在缓存层返回答案不经过模型推理。多级路由先用小模型处理简单问题只有复杂问题才路由到大模型。落地优先级建议先从系统和缓存入手见效最快再逐步尝试量化压缩最后才是蒸馏新模型。5.3 成本控制的工程思路成本控制不只是在推理环节做优化还需要在业务层设计好机制成本项控制方案Token 消耗精简 Prompt、限制 max_tokens、使用语义缓存算力消耗低峰期缩容、高峰期弹性扩容、GPU 共享检索成本对向量索引做量化、分层检索降低召回计算量人效成本建立模型评测体系减少人工回归验证时间这里再提一个容易被忽略的点不要盲目追求大模型。很多业务诉求用一个小模型 规则引擎就能解决上线成本低、延迟低、可控性强。把大模型用到最需要语义理解的地方是最经济也最稳妥的策略。6. AI 应用落地从 Demo 到生产环境6.1 可观测性日志、链路追踪与评估AI 应用相比传统后端应用多了一个“不确定性”维度。同一个 Prompt今天的输出和明天可能不同而且每一次输出都可能是错的。因此可观测性不只是看有没有报错更要看质量。生产环境中至少需要记录请求的完整 Prompt 和模型输出RAG 召回的相关文档和得分Agent 每一步的工具调用参数和结果模型的 Token 消耗和响应延迟用户的显式反馈点赞、点踩。有了这些数据才能回答两个关键问题某个功能效果为什么下降哪类请求浪费了最多成本6.2 安全与合规幻觉、注入、隐私大模型应用的安全问题比传统应用更复杂。常见风险包括提示词注入用户恶意构造 Prompt诱导模型执行非预期指令。解决方案是对用户输入做敏感词过滤并对系统指令做强约束。幻觉输出模型回答与事实不符。RAG 可以在一定程度缓解但必须保留“根据已知资料无法回答”的兜底话术。隐私数据泄露企业内部数据进入模型后可能被其他请求检索到。解决思路是严格的权限隔离以及私有化部署方案。上线前建议做至少一轮红队测试Red Teaming模拟恶意用户、边界输入、数据投毒等场景。6.3 Java 后端集成示例很多企业后端是 Java 技术栈下面给出一个 Spring Boot 调用大模型接口的最小示例。// 文件路径src/main/java/com/example/ai/gateway/AiGateway.java package com.example.ai.gateway; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import org.springframework.http.*; import java.util.List; import java.util.Map; Component public class AiGateway { Value(${ai.api-key}) private String apiKey; Value(${ai.base-url}) private String baseUrl; private final RestTemplate restTemplate; public AiGateway(RestTemplate restTemplate) { this.restTemplate restTemplate; } public String chat(String userMessage) { String url baseUrl /chat/completions; HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setBearerAuth(apiKey); MapString, Object body Map.of( model, gpt-4o-mini, messages, List.of( Map.of(role, user, content, userMessage) ), temperature, 0.3 ); HttpEntityMapString, Object request new HttpEntity(body, headers); ResponseEntityMap response restTemplate.exchange(url, HttpMethod.POST, request, Map.class); if (response.getBody() ! null) { List? choices (List?) response.getBody().get(choices); if (!choices.isEmpty()) { Map?, ? firstChoice (Map?, ?) choices.get(0); Map?, ? message (Map?, ?) firstChoice.get(message); return (String) message.get(content); } } return AI 服务返回异常; } }配套配置# 文件路径src/main/resources/application.yml ai: api-key: ${AI_API_KEY:your-api-key} base-url: ${AI_BASE_URL:https://api.openai.com/v1}生产环境中建议把RestTemplate换成WebClient或Spring AI这类更完善的集成组件并配置连接池、超时、重试和熔断。7. 常见问题与排查思路7.1 问题排查表问题现象常见原因解决思路RAG 检索结果不相关Embedding 模型效果差 / chunk 切分不合理更换 Embedding 模型调整 chunk 大小加入重排序模型回答引用错误文档检索到了语义相近但内容不符的文本增加元数据过滤结合关键词 BM25 混合召回Agent 反复调用同一个工具工具描述不清晰 / 缺少终止条件优化工具描述设置最大迭代次数增加日志大模型响应延迟高上下文过长 / 模型参数量过大压缩 Prompt使用小模型开启流式输出Token 成本快速飙升Prompt 冗余 / 无限流 / 缓存缺失精简 Prompt加入语义缓存设置预算告警系统提示词被绕过提示词注入攻击输入过滤强约束系统指令敏感场景人工审核7.2 典型问题详解在这里挑一个最容易复现的问题展开讲RAG 检索结果不相关。排查顺序建议先看召回文档本身是否相关。直接查询向量库用同一个问题翻看 top_k 返回的文本块。召回文档相关但回答还是不行说明是 Prompt 组装或模型理解问题优先调 Prompt。召回文档不相关优先检查 Embedding 模型和 chunk 切分。如果切分太碎尝试加大 chunk或改用父子分块策略检索子块返回父块。如果向量检索不如预期考虑引入关键词召回做混合检索再用重排序合并结果。这类问题从来不是单点原因必须靠日志和评测数据定位。8. 最佳实践与工程建议8.1 技术侧建议第一建立评测集。没有评测集就无法判断一次 Prompt 改动到底是变好还是变坏。评测集至少包含 100 条真实业务问题并覆盖关键边界场景。第二所有外部依赖都要有兜底。大模型 API 可能超时、限流、返回异常要让业务有降级方案。比如检索失败时可以返回“对不起我暂时无法查询”而不是让整个接口 500。第三重视幂等设计。Agent 可能会重复执行下单、发送通知等操作必须在工具层做幂等控制否则一次重试就可能产生重复工单。第四日志中禁止记录完整敏感数据。如果应用涉及手机号、身份证号、企业合同内容日志必须脱敏向量库中的文档也要按权限分级。8.2 组织与流程侧建议AI 应用开发不能只靠算法工程师。一个成熟的项目团队通常需要后端工程师负责系统稳定性和接口封装算法工程师负责 Prompt、RAG、模型效果数据工程师负责知识库的更新和清洗测试工程师负责评测集构建和线上回归。团队内部要建立 Prompt 版本管理机制。最简单的方式是把 Prompt 模板放进 Git 仓库每次修改走代码评审流程避免线上配置被随意改动。8.3 面向窗口期的准备如果目标真的是走向资本市场从技术角度可以提前准备三件事成本数据可解释。能够说清楚单次请求的算力成本、各环节成本占比以及成本下降的路径。效果数据可量化。有完整的评测体系证明模型效果稳定而不是靠一两个演示 Demo。安全合规可审计。能够向监管和客户说明数据从采集、存储、处理到输出的完整链路。这些都不是短期能补出来的需要从产品第一天就建立意识和制度。9. 总结与学习路线本文从“大模型公司上市窗口期”这个商业话题切入落到了更实在的技术工程化问题上。我们动手实现了一个基于 FastAPI 和向量数据库的 RAG 服务写了一个完整的 Function Calling Agent 示例并讨论了推理性能优化、生产环境落地和常见问题排查。这些能力几乎是大模型应用团队走向成熟必须跨过的门槛。如果你刚接触这个方向建议按以下顺序学习先跑通 OpenAI 兼容接口的基本调用理解 Chat Completion 和 Embedding 的区别把本文的 RAG 服务跑起来自己替换成业务文档观察检索效果尝试给 Agent 增加新的工具比如查数据库、调内部 API了解 vLLM 和向量数据库的原理尝试用 Docker 搭建一套私有化环境最后把评测和可观测性补上形成一套自己可以依赖的 AI 应用工程框架。资本市场的窗口期是不是已经关闭没人能准确预测。但有一点是确定的无论窗口期什么时候到来技术底座的深度和稳定性都会决定这家公司能走多远。与其关注“是否 IPO”的新闻不如把精力花在亲手构建真正经得起规模考验的 AI 应用上。
返回列表