把大模型应用从“能跑通”推到“敢上线”,中间隔着一条挺深的河。我最近完整经历了一个从零搭建AI服务到生产环境稳定运行的落地过程,期间踩过模型幻觉、Token超限、接口超时、内存泄漏这些坑,也沉淀了一套相对清晰的打法。这篇文章就把我认为最有复用价值的经验整理出来,从技术选型、架构设计、核心编码到部署验收、故障排查,一次性讲透。
文章更适合两类人看:一是已经用LangChain或相关框架写过Demo,准备往生产环境推的开发者;二是团队刚立项,需要在技术选型和架构层面做决策的技术负责人。文章不会讲太多基础概念,重点放在“生产环境里真正要命的问题”上。
1. 先把生产落地的核心逻辑想清楚
1.1 为什么AI应用开发和传统后端开发不一样
很多人第一次把AI应用往生产推的时候,会下意识沿用传统后端那套方法论:定义好接口、写好业务逻辑、压测、上线、监控。这套流程没错,但AI应用有几个传统后端很少面对的特殊变量。
第一个变量是输出的不确定性。传统接口的返回值是确定的,参数一样结果必然一样。大模型接口不一样,同样的Prompt、同样的参数,两次返回的内容可能有细微差别,甚至偶尔会给出完全偏离预期的结果。这个特性直接影响接口设计、缓存策略和错误处理方式,不能简单套用传统Web开发的经验。
第二个变量是成本模型完全不同。传统接口的成本主要在服务器资源和带宽,边际成本低且好预估。大模型接口的成本和Token数量强相关,用户多问一句话、上下文里多塞一份文档,成本就上去了。如果不在架构层面做控制,月底账单会让人措手不及。
第三个变量是性能瓶颈从“应用服务器处理不过来”变成了“外部模型接口响应太慢”。一次请求动辄几秒到十几秒,远远超过传统接口的几百毫秒标准。前端交互、超时设置、用户体验设计,都得围绕这个现实重新考虑。
第四个变量是评测方式不一样。后端功能对不对,写测试用例断言就行。AI应用怎么判断“回答得好不好”?语义准确、格式规范、不胡说八道,这些指标很难用传统自动化测试覆盖。
理解了这四个差异,再看后续的技术方案,很多设计决策就顺理成章了。
1.2 生产级AI应用的五大技术选型思路
选型是项目最先遇到的关卡。我的经验是,把决策拆成五个层面,逐层定,每一层都有明确的原则。
第一层是模型的选择。现在主流路线无非三种:调用云端大模型API、部署开源模型、用云端模型加私有化部署混合。我的建议很直接:业务刚起步、对数据敏感度没有极高要求,直接选国内成熟的云端API或海外厂商的稳定版API,别自己折腾部署。只有当延迟、成本或数据合规要求达到一个临界值,再考虑私有化。选模型还有个细节容易被忽略——模型版本一定要锁定,不要默认用“latest”之类的不固定别名,否则模型厂商升级版本后,你的业务输出可能悄悄变化,线上问题排查起来非常被动。
第二层是开发框架。目前主流选择包括LangChain、LlamaIndex,以及在Java生态里用得越来越多的Spring AI。框架的作用是屏蔽不同模型厂商的API差异,提供Prompt模板、工具调用、RAG这些通用能力。我的建议是:不要贪多求全,选择自己团队技术栈最匹配的。比如团队是Java后端背景,Spring AI的学习曲线明显更平缓,和Spring Boot配置体系的融合也更自然。
第三层是外部环境的准备。模型要接进来,至少需要一套Key管理体系,密钥不能裸奔在前端代码里,后端要有统一的转发层。如果业务涉及多个模型来源,还要有降级切换的机制。这层投入不大,但直接影响系统稳定性和安全性。
第四层是数据层。AI应用和数据库的结合方式比传统应用丰富得多。最常用的是向量数据库,用于语义检索和知识库问答;但关系型数据库依然不可或缺,用来记录用户的对话历史、存储业务数据、维护状态。选型时一定要把这两类数据库的分工想清楚,否则很容易在数据一致性上栽跟头。
第五层是可观测性。传统应用看QPS、错误率、响应时间就够了,AI应用还得多看一层:模型调用耗时、Token消耗量、上下文窗口占用率、幻觉发生频率。没有这一层数据,后面做优化全凭感觉。
2. 架构设计与细节参数,决定上线后能不能睡安稳觉
2.1 请求链路上的四个关键环节
一个典型的AI应用生产请求链路,我习惯拆成四个环节,每个环节都有需要重点把控的设计点。
第一个环节是接入层。用户请求进来后,先做身份认证、限流、参数校验,这些和传统网关没什么区别。但AI应用在接入层还要做一层内容安全检查,无论是用户输入还是模型输出,都要过一遍敏感信息过滤器,防止用户提出恶意指令或模型生成不合规的内容。这一层往往被重视得不够,等出了事再补就晚了。
第二个环节是上下文装配。这步是AI应用和后端业务逻辑结合最紧密的地方。在请求发给模型之前,系统需要从数据库中取出用户的对话历史、检索出相关的知识库片段,把它们和系统Prompt、用户当前问题一起组装成完整的上下文。这个环节决定了一个AI应用回答得好不好,远不止“把Prompt写漂亮”那么简单,还要考虑上下文窗口限制、Token预算分配、历史记录截断策略等一系列工程细节。
第三个环节是模型调用。这里重点是流式输出和非流式输出的选择、超时控制、重试机制、多模型降级策略。生产环境下绝对不能把请求调成“死等”,必须有严格的超时熔断机制。
第四个环节是结果后处理。模型返回的原始内容通常不能直接给用户,要经过格式清洗、结构化解析,如果请求的是JSON格式,还得处理模型偶尔输出不合法JSON的情况。该落库的落库、该触发后续流程的触发后续流程,这才算一个完整的闭环。
这四个环节环环相扣,每一环出问题都会影响最终效果。后面我会针对每个环节给出更具体的实现方案。
2.2 提示词工程与上下文管理的实操细节
提示词在Demo阶段怎么玩都行,一旦上生产,就必须把管理规范立起来。我的做法是全公司统一维护一个提示词版本库,每条提示词都对应一个版本号,需要调整时走更新流程并记录变更原因。这样做的好处太多了:线上效果不佳时,能够快速回滚到旧版本;模型厂商升级后行为变化,能够定位是不是提示词过时了。而不会出现“明明没人动过代码,效果怎么变了”这种诡异问题。
提示词本身要遵循几个基本原则。一是职责单一,一条提示词只干一件事,别把角色设定、知识库指令、输出格式要求混在一起。二是明确约束边界,最好用“必须”和“禁止”做正反两个方向的约束,而不是一味描述“你应该是什么”。三是给模型留出足够的推理空间,复杂问题可以要求“先分析再回答”,比直接要求“直接给出答案”效果更好。
上下文管理是AI应用生产落地里最容易忽视的细节。大模型的上下文窗口有限,而且输入Token数量直接影响响应速度和成本。很多公司的知识库文档一多,就想全塞进上下文里,结果要么超出窗口报错,要么响应极慢、成本飙升。正确的思路是做分层:明确的用户意图和最新消息放前排,历史消息做摘要压缩,知识库内容只放和当前问题最相关的片段。这个“最相关”怎么算,就是向量检索要解决的问题,后面在RAG部分详细讲。
2.3 Agent、RAG、模型微调,怎么选
做AI应用迟早会面对这个问题:我的场景需要Agent、RAG还是微调?我的答案是,三者的定位完全不同,很多场景还可能需要组合使用。
RAG主要解决“模型不知道的事”,也就是知识时效性和私有知识的问题。模型训练数据有截止时间,企业内部文档、实时数据它根本不知道。RAG的做法是在回答前先从外部知识库检索相关内容,塞进上下文里让模型参考。它不改变模型本身,适合知识库问答、企业文档助手、政策法规查询这类场景。RAG是绝大多数业务场景最优先考虑的方案,因为见效快、可解释性强、知识更新成本低。
微调主要解决“模型做不好的事”,也就是希望模型模仿某种特定的语气风格、输出结构或遵循特定的专业术语。微调需要准备高质量的数据集,需要训练和评估成本,而且效果具有不可逆性——模型一旦被微调,它在其他通用能力上可能有一定程度的衰减。适用于任务非常稳定的场景,比如代码生成、特定行业的文本分类、企业内部的意图识别。
Agent的执行能力更突出,解决“模型光说不动”的问题。它让模型能调用外部工具、查询数据库、操作API,把一个复杂的任务拆解成多步执行。典型场景包括智能客服需要查订单、AI编程助手需要读写代码、数据分析助手需要操作数据库。但Agent也是三个方案里最难控制稳定性的,多步推理中的任何一步出错都会被放大,生产环境必须有严格的审核机制。
我的建议是,不要一上来就上Agent,用最简单的方式把核心链路跑通。比如RAG能解决80%的问题,就从RAG开始,等积累足够多的真实用户反馈,明确知道哪些场景需要多步工具调用,再逐步引入Agent。生产环境最怕的是架构过度复杂,问题排查起来像大海捞针。
2.4 成本、延迟与并发:上线前的三个量化指标
传统后端上线主要关心服务器规格够不够,AI应用要复杂的多。我建议在写第一行业务代码前,先把三个量化指标估算清楚。
第一个是单次请求的平均Token消耗。用开发环境的真实对话数据做样本,计算平均每轮对话消耗的输入Token和输出Token。注意输入Token不止是用户那句话,还包括系统Prompt、历史记录、检索出来的知识片段,这部分的体量往往比用户输入更大。有了这个数据,再乘以预计日活,就能估算出当月的模型调用成本。很多公司上线后才拍脑袋发现预算不够,就是因为漏算了上下文中的隐形成本。
第二个是端到端延迟。要分别测三段时间:模型首字返回时间、整个流式响应完成时间、以及包括检索和上下文装配在内的整体耗时。用户能感知到的主要是前两段。如果发现首字返回太慢,优先检查是不是上下文太长、模型规格太大,或者网络链路有没有绕路。
第三个是并发上限。这里要同时算两层,一层是应用服务的并发能力,这取决于你的服务配置和负载均衡策略;另一层更重要——模型API的配额限制,几乎所有云端模型API都有TPM(每分钟Token)和RPM(每分钟请求数)限制。如果不提前做限流和排队,一旦流量上来,最先崩的反而是外部API调用,报错信息往往还不太明显。
我用一个具体场景来算一笔账。假设一个智能客服应用,系统Prompt约500Token,每轮历史记录平均1000Token,问题平均50Token,回答平均300Token。单次请求的总Token大约是1850Token。如果每天1万次请求,一个月的消耗就是1850乘以10000乘以30,等于5.55亿Token。按主流模型的定价估算,这已经不是一笔小数目。但如果做好历史消息摘要、把系统Prompt控制在300Token以内、知识库只检索最相关的几百Token,单次消耗降到800Token以下,成本能直接压缩一半以上。这就是为什么我一直强调,成本不是上线后才控制的,而是在架构设计阶段就要考虑的。
3. 一次完整的生产落地实操记录
3.1 工程初始化与依赖配置
理论说得再多,不如上手走一遍。这一节我用一个企业知识库问答助手作为示例项目,完整演示从工程初始化到部署上线的过程。技术栈选型上,后端用Java 17加Spring Boot 3加Spring AI,前端用简单的Web页面做演示,数据库用PostgreSQL加pgvector实现向量检索,部署用Docker Compose编排,这种组合在Java团队里落地成本最低。
先创建Spring Boot工程。如果你用的是Spring Initializr,版本选3.2以上,Boot版本太低的话Spring AI的兼容性会有问题。依赖上需要引入Spring Web、PostgreSQL驱动和Spring AI相关的模块。
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> <version>1.0.0-M6</version> </dependency> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-pgvector-store-spring-boot-starter</artifactId> <version>1.0.0-M6</version> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <scope>runtime</scope> </dependency>需要注意Spring AI目前的版本迭代很快,API层面有一些微调,一定要锁定一个版本并在项目里固定下来。我把版本写在Maven的版本属性里统一管理,尽量避免不同模块依赖版本不一致导致的诡异错误。
配置文件方面,核心配置就是模型API地址、密钥和向量库的连接信息。我习惯把这些配置放到环境变量或者配置中心里,代码仓库只保留模板文件,避免密钥泄露。
spring: ai: openai: base-url: ${AI_BASE_URL} api-key: ${AI_API_KEY} chat: options: model: ${AI_MODEL_NAME:gpt-4o-mini} temperature: 0.3 max-tokens: 1024 datasource: url: jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME} username: ${DB_USER} password: ${DB_PASSWORD}这里特别强调temperature参数,生产环境的对话问答场景建议设置在0到0.3之间,越低输出越稳定。有些团队默认用API的默认值,那往往偏高,生成结果发散的状况会让人抓狂。
3.2 构建流式对话接口
AI应用的对话接口,强烈建议用流式输出。原因很简单:大模型生成完整回答需要几秒甚至十几秒,如果等全部生成完再一次性返回,前端长时间白屏,用户的体验会非常糟糕。流式输出让用户第一时间看到第一个字,配合打字机效果,心理等待时间大大缩短。
Spring AI的流式接口实现比较简洁。我写一个Controller,接收用户消息和会话ID,通过ChatClient的stream方法把模型输出以SSE格式推送给前端。
@RestController @RequestMapping("/api/chat") public class ChatController { private final ChatClient chatClient; private final ConversationService conversationService; public ChatController(ChatClient.Builder chatClientBuilder, ConversationService conversationService) { this.chatClient = chatClientBuilder.build(); this.conversationService = conversationService; } @PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public Flux<String> streamChat(@RequestBody ChatRequest request) { // 1. 从数据库加载历史会话 List<Message> history = conversationService.loadHistory(request.sessionId()); // 2. 组装包含历史记录的Prompt Prompt prompt = conversationService.buildPrompt(request.message(), history); // 3. 流式调用模型 return this.chatClient.prompt(prompt) .stream() .content(); } }这看起来不复杂,但数据库的会话记录缓存和历史截断策略很关键,系统Prompt与用户输入之间的平衡也需要在前置服务层做好。我见过不少团队流式接口很快接出来了,但把系统提示、历史、知识库片段一股脑全塞给模型,导致Token消耗和响应延迟双双失控。
3.3 给AI接入企业知识库:搭建RAG流程
接下来是知识库问答系统的核心——RAG流程。整个流程分两步:第一步是文档的离线索引阶段,把企业文档切块、向量化、写入向量数据库;第二步是在线问答阶段,用户提问后先检索相关文档片段,再把片段塞入上下文让模型回答。很多教程只演示了第二步,但生产环境真正麻烦的是文档更新和索引的维护。
文档切块是非常影响检索质量的一步。切得太碎,语义被切断,检索精度下降;切得太大,每个块包含太多冗余信息,塞进上下文浪费Token。我的经验是,一般文档按500到800字切块,块与块之间保留50到100字的重叠,确保跨块语义不断裂。代码文档可以按照类或方法进行结构化切分,效果更好。
在线问答的流程里,我一般会在标准的“检索-增强-生成”上加一个“改写”环节,先让模型判断用户的意图、提取关键词,再去做向量检索。这个改写的成本很低,但能显著提高检索命中率,尤其当用户的提问用语比较口语化、和文档里的书面表达差距较大的时候,效果尤为明显。
下面是向量检索和回答生成的核心代码。
@Service public class RagService { private final VectorStore vectorStore; private final ChatClient chatClient; public String answer(String question) { // 1. 构造查询向量,执行相似度检索 List<Document> documents = vectorStore.similaritySearch( SearchRequest.builder() .query(question) .topK(4) .similarityThreshold(0.5) .build() ); // 2. 将检索结果组装成上下文 String context = documents.stream() .map(Document::getContent) .reduce("", (a, b) -> a + "\n\n" + b); // 3. 构造系统提示词,要求模型基于上下文回答 String systemPrompt = """ 你是企业知识库助手。请根据提供的资料回答问题。 如果资料中没有相关内容,请明确告知用户“资料库中暂无相关信息”,不要编造。 回答时引用资料中的关键信息,保持简洁准确。 参考资料: %s """.formatted(context); // 4. 调用模型生成回答 return chatClient.prompt() .system(systemPrompt) .user(question) .call() .content(); } }注意几个生产级细节。similarityThreshold设的是相似度过滤阈值,避免检索到完全不相关的内容还硬塞给模型。topK的数量不要贪多,4到5个片段已经足够回答大多数问题,塞太多反而稀释重点、推高成本。系统提示词里那句“资料中没有就直说不知道”,是控制幻觉最直接有效的手段,我强烈建议所有知识库场景都加上。
3.4 Docker化部署与启动参数调优
工程开发完成后,部署环节有几个很容易栽跟头的点。直接上Dockerfile和Compose配置,逐行说明关键细节。
FROM eclipse-temurin:17-jre WORKDIR /app COPY target/*.jar app.jar EXPOSE 8080 ENV JAVA_OPTS="-Xms512m -Xmx1024m -Dfile.encoding=UTF-8" ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]JVM参数别照抄默认值,要根据实际压测结果调。AI应用的内存大头通常在向量计算和请求并发上。JVM堆内存设太大浪费资源,设太小容易频繁GC导致接口延迟抖动。建议先设置Xms和Xmx相同值,减少运行期堆扩容带来的性能波动,再根据压测数据二次调整。
Docker Compose把应用服务和PostgreSQL编排到一起。
version: "3.8" services: postgres: image: pgvector/pgvector:pg16 environment: POSTGRES_DB: ai_app POSTGRES_USER: ai_user POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - pgdata:/var/lib/postgresql/data ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U ai_user -d ai_app"] interval: 5s timeout: 3s retries: 5 app: build: . ports: - "8080:8080" environment: AI_BASE_URL: ${AI_BASE_URL} AI_API_KEY: ${AI_API_KEY} DB_HOST: postgres DB_PORT: 5432 DB_NAME: ai_app DB_USER: ai_user DB_PASSWORD: ${DB_PASSWORD} depends_on: postgres: condition: service_healthy volumes: pgdata:这里我用的是pgvector官方的PostgreSQL镜像,它内置了向量类型和索引支持,起一个容器就把关系型数据库和向量数据库都解决了,省去额外维护一套向量数据库的运维成本。
3.5 上线前的验收清单
真正上线前,我建议团队按照下面的清单逐项过一遍,每一项我都实际踩过坑:
- 流式响应是否在弱网环境下稳定不断线,前端断线重连逻辑是否已处理。
- 用户输入超长时是否会被优雅地截断或提示,而不是直接报错。
- 多个用户同时提问时,接口响应时间是否在可接受范围内,是否触发过模型API限流。
- 模型偶尔生成不合法内容时,内容安全过滤是否正常工作。
- 回答内容是否会被记录到日志里,日志系统是否会因为对话内容产生合规风险。
- 模型服务不可用时,系统是否具备降级能力,比如返回提示文案或切换到备用模型。
- 整个链路的监控指标是否齐全,包括Token消耗、模型延迟、检索命中率、用户满意度。
这份清单覆盖了功能正确性以外的运维、成本、安全、体验多个维度。千万别觉得功能能跑就等于生产可用了,AI应用的项目管理和传统软件有本质区别,不确定性因素太多,没有验收机制就上线,后面要付出的代价是巨大的。
4. 常见故障与排查技巧实录
4.1 服务不稳定:超时、幻觉、上下文泄漏
生产环境跑起来之后,各种问题才开始真正暴露。这里挑几个最典型、最让人头疼的故障场景,说说我的排查思路。
第一个是模型接口超时。表现是用户等了好久没反应,或者前端直接报错。排查时不要一上来就怀疑网络,先看是不是上下文太大,把模型的处理时间撑爆了。我遇到过最夸张的一次,系统里塞了几万字的文档还要求模型做总结,接口直接超时。解决思路是限制上下文长度,超长内容先做摘要,再用摘要去提问。
第二个是幻觉问题。模型一本正经地编造知识库中不存在的信息,这种情况在知识库问答场景里最常见。我排查的时候会先看检索环节有没有问题,经常是检索出来的片段和问题完全不相关,模型只能硬着头皮自己编。把相似度阈值调高、优化文档切块逻辑,基本能解决大部分问题。还有一层兜底方案,就是在结果返回前加一个“内容校验”环节,用规则或小模型做一次相关性打分,低于阈值的回答统一提示“资料不足,无法回答”。
第三个是上下文泄漏。这个问题的隐蔽性特别强。当多个用户会话共用一个上下文缓存,或者检索模块把文档内容错配到其他业务的上下文中,就容易把A用户的信息暴露给B用户。排查时重点检查对象缓存的生命周期管理,会话维度的数据必须严格按sessionId隔离,任何涉及用户数据的模块都要默认隔离而不是默认共享。
4.2 成本失控与限流:怎么定位异常消耗
AI应用上线后成本突然翻倍,是另一个常见的“惊喜”。我建议先看监控面板的Token消耗趋势,如果某个时间点开始爬升,基本可以锁定是代码改动或用户行为变化引起的。
有一种隐蔽的成本坑是循环调用。比如你在Agent里设计了工具调用,模型为了完成一个任务连续循环调用某个工具几十次,每次都消耗Token,成本会在不知不觉中飙升。解决方法是给Agent设定最大迭代次数,超过阈值自动终止。
还有一种是“用户灌长文”攻击。用户故意输入超长文本,系统不加限制地把全文塞进上下文,成本随之暴涨。防御手段是在接入层做输入长度限制,超过预设阈值就拦截或提示。这个限制不仅是为了保护模型,更是为了保护你的钱包。
限流策略方面,我的经验是要在应用层做双层限流:一层针对用户维度,限制单用户每分钟的请求数,防止个别用户滥用;另一层针对全局API配额,设置整体的调用频率上限,防止突发流量打爆模型API。一旦触发限流,要返回明确的错误码和提示文案,让前端可以友好地向用户解释“当前人多,稍后再试”。
4.3 一个完整的排查过程实录
举个真实发生的例子,我们的服务某天突然接到大量用户投诉,说是回答质量明显下降。查监控发现模型接口的正常率没有异常,但平均响应耗时上升了很多,Token消耗也明显增加。
进一步查日志,发现从当天早上开始,上下文系统日志里出现了大量长文本记录,原因是产品侧为了提升回答质量,悄悄把“返回最近20条聊天记录”改成了“返回最近两小时的全部聊天记录”。结果就是上下文越来越长,每次请求的Token不断上涨,响应变慢、质量反而下降,因为太古老的对话内容对当前问题反而是干扰。
定位很快,修复也简单,把上下文策略改回“限制条数加摘要压缩”,响应速度立刻恢复。但这个问题给我们的教训很深:AI应用的任何参数调整,哪怕是产品侧觉得“无伤大雅”的改动,都可能引起蝴蝶效应。所以我们后面上线了一个配置管理规范,所有影响上下文、Token、模型参数的变更,必须走技术评审和灰度流程。
4.4 常用排查工具与指标速查表
最后把常用的排查指标和工具整理成一份速查表。我每次排查问题都会先过一遍这张表,大多数问题都能快速定位到方向。
| 问题现象 | 优先查看指标 | 常用排查手段 |
|---|---|---|
| 响应超时 | 模型调用耗时、上下文Token数 | 检查上下文是否超长,是否有检索阶段耗时过高 |
| 回答内容错误 | 检索命中文档相关性、提示词版本 | 检查向量检索结果得分,比对提示词最近变更 |
| 成本突增 | Token消耗趋势、单请求平均Token | 查看是否有循环调用、长文本注入、上下文膨胀 |
| 接口被限流 | 模型API配额用量、错误码429 | 检查全局并发策略,必要时申请提升配额 |
| 幻觉明显 | 检索阈值、文档切块边界 | 调高相似度阈值,优化切块策略 |
| 用户数据串线 | 会话隔离逻辑、缓存Key设计 | 代码审查会话维度变量,检查缓存生命周期 |
排查AI应用的问题,核心原则是先看数据再看代码。监控面板上的Token消耗趋势、模型调用耗时、检索得分分布,这些数据往往比日志更能快速告诉你问题出在哪个环节。没有数据支撑的排查,无异于盲目试错。
我个人在实际操作中最深的体会是:AI应用的生产落地,难点不在模型,而在模型之外的工程体系。把提示词当代码一样管理、把Token当服务器资源一样监控、把AI应用当做有“不确定性”的系统来设计,才能真正把大模型的能力转化为稳定的业务价值。这一路踩过的坑很多,希望这篇文章能帮你少走一些弯路。后面我再单独写写多模态场景和复杂Agent系统的落地经验,到时候再来聊。