ARTICLE DETAIL

资讯详情

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

AI应用架构设计实战:从模型接入到Agent编排的分层指南

AI应用架构设计实战:从模型接入到Agent编排的分层指南 1. 从一张架构图说起AI应用到底该怎么搭这两年AI应用开发的热度不用我多说身边做后端的朋友、做运维的兄弟、甚至做前端的小伙伴都在琢磨怎么把手里的业务和LLM接上。但真动手的时候十个人里有八个会卡在同一个地方架构到底怎么设计。不是模型选型的问题也不是Prompt写得好不好的问题而是整个应用的骨架没搭对导致后面越写越乱加个记忆功能要重构接个工具调用又要重构最后变成一坨谁都不敢碰的代码。我拿图解AI应用架构设计这个题目来聊不是要给你画一张漂亮的PPT架构图而是想把这张图背后的每一层拆开告诉你每一层为什么存在、解决什么问题、实际落地时踩过哪些坑。核心关键词就几个AI应用、架构设计、Agent、LLM、MCP。这几个词基本覆盖了当前AI应用开发的主干。不管你是刚入门想搞清楚AI应用开发学习路线的还是已经在做Agent项目想优化架构的这篇内容都能给你一些可以直接抄作业的东西。先说清楚这篇东西适合谁看。如果你是完全没接触过LLM的小白建议先补一下LLM是什么这个基础概念简单说就是大语言模型你给它一段文字它给你生成一段文字本质是个概率模型。如果你已经知道LLM是什么但不知道怎么把它变成一个能用的产品那这篇就是写给你的。如果你已经在做AI Agent开发但觉得架构混乱、并发扛不住、工具调用老出问题那这篇里的排查思路和架构分层应该能帮到你。我自己的经验是AI应用架构设计和传统后端架构设计最大的区别在于传统架构里输入和输出是确定的AI应用里输入和输出都是概率性的。这个根本差异导致整个架构的每一层都要重新思考。你不能像写CRUD那样写AI应用因为LLM的返回是不稳定的Agent的行为是不可预测的工具调用的结果可能是失败的。所以架构设计的核心目标就变成了在不确定性的基础上构建一个足够稳定、可观测、可扩展的系统。下面我按分层的方式从最底层的模型接入层往上讲一直讲到最上层的应用编排层中间会穿插MCP协议、Agent架构、并发处理、安全防护这些实际开发中绕不开的话题。每一层我都会说清楚它解决什么问题、为什么这么设计、实际怎么落地、容易踩什么坑。2. 模型接入层LLM不是随便调个API就完事2.1 为什么模型接入需要单独一层很多人觉得调LLM就是发个HTTP请求拿回结果就完事了。我一开始也这么想直到线上出了几次事故才明白模型接入层必须单独抽象出来。原因有三个第一模型供应商会变今天用这家明天用那家如果业务代码里到处散落着API调用换模型的时候你会想死第二不同模型的参数格式、返回结构、错误码都不一样需要统一适配第三模型调用有失败率需要重试、降级、熔断这些逻辑不应该侵入业务代码。我见过最离谱的一个项目业务代码里直接写死了某家模型的API地址和密钥后来要换模型改了三十多个文件。这就是没有模型接入层的代价。正确的做法是定义一个统一的模型接口所有业务代码只依赖这个接口底层具体用哪家模型、怎么调由接入层封装。class LLMProvider: def chat(self, messages, toolsNone, **kwargs): raise NotImplementedError class OpenAIProvider(LLMProvider): def chat(self, messages, toolsNone, **kwargs): # 适配OpenAI格式 pass class AnthropicProvider(LLMProvider): def chat(self, messages, toolsNone, **kwargs): # 适配Anthropic格式 pass这个抽象看起来简单但它是整个AI应用架构的基石。没有这一层后面所有的Agent、工具调用、记忆管理都无从谈起。2.2 模型选型的实际考量选模型不是看排行榜就完事了。我实际做项目的时候主要看四个维度能力、成本、延迟、稳定性。能力包括推理能力、工具调用能力、长文本处理能力成本按token算输入输出价格可能不一样延迟直接影响用户体验稳定性包括可用性和返回质量的一致性。举个例子如果你做的是代码生成类的AI应用那模型的选择和做客服机器人的选择完全不同。代码生成对推理能力要求高可以接受稍高的延迟客服机器人对延迟敏感但推理能力要求没那么高。再比如如果你的应用需要频繁调用工具那模型的function calling能力就是关键指标有些模型虽然通用能力强但工具调用格式老出错这种就不能用。我一般会做一个简单的对比表格把候选模型的关键指标列出来然后根据业务场景打分。这个表格不需要很复杂但一定要有因为模型更新很快今天合适的明天可能就不合适了有个表格方便随时重新评估。维度模型A模型B模型C推理能力强中强工具调用支持支持弱输入价格低中高输出价格中低高平均延迟2s1s3s可用性99.9%99.5%99.9%注意模型选型不是一次性的工作建议每季度重新评估一次因为模型迭代速度太快了。2.3 统一错误处理和重试机制LLM调用失败是常态不是异常。网络抖动、限流、模型过载、返回格式错误这些都会发生。我踩过最大的坑就是没有做统一错误处理结果线上一个模型限流整个应用全挂了。正确的做法是在模型接入层做统一的错误分类和重试。错误大致分三类可重试错误如限流、超时、不可重试错误如参数错误、认证失败、降级错误如模型不可用需要切换到备用模型。可重试错误用指数退避重试不可重试错误直接抛给上层降级错误触发备用模型。import time from functools import wraps def retry_with_backoff(max_retries3, base_delay1): def decorator(func): wraps(func) def wrapper(*args, **kwargs): for attempt in range(max_retries): try: return func(*args, **kwargs) except RateLimitError: if attempt max_retries - 1: raise time.sleep(base_delay * (2 ** attempt)) except (AuthError, InvalidRequestError): raise return None return wrapper return decorator这个重试装饰器看起来简单但实际用起来很稳。关键是区分错误类型不要所有错误都重试那样只会浪费时间和token。3. Agent架构让LLM从聊天机器人变成执行者3.1 Agent到底是什么和普通LLM调用有什么区别Agent这个词现在被用得很泛但核心区别就一个普通LLM调用是单轮的Agent是多轮的而且能调用工具、能根据结果决定下一步做什么。你可以把普通LLM调用理解成问一句答一句把Agent理解成给它一个目标它自己规划步骤、调用工具、检查结果、调整策略直到完成目标。我经常用生活类比来解释普通LLM调用就像你问路人最近的加油站怎么走他告诉你方向就结束了Agent就像你雇了一个司机你说我要去机场他会自己看导航、加油、避开拥堵、把你送到目的地。区别在于Agent有自主性和工具使用能力。Agent架构的核心组件包括规划模块决定下一步做什么、记忆模块记住之前发生了什么、工具模块能调用哪些外部能力、执行模块实际执行动作。这四个模块缺一不可少了任何一个Agent要么变成无头苍蝇要么变成只会聊天的废物。3.2 ReAct模式最经典的Agent架构ReActReasoning Acting是目前最主流的Agent架构模式核心思想是让LLM交替进行推理和行动。每一轮LLM先输出思考过程Thought然后决定调用哪个工具Action工具返回结果后ObservationLLM再根据结果继续思考直到得出最终答案。这个模式为什么有效因为它把复杂的任务拆解成了思考-行动-观察的循环每一步都有明确的输入输出LLM不需要一次性规划所有步骤只需要决定下一步做什么。这大大降低了LLM的推理难度也提高了成功率。def react_agent(query, tools, max_steps10): messages [{role: user, content: query}] for step in range(max_steps): response llm.chat(messages, toolstools) if response.is_final_answer: return response.content tool_result execute_tool(response.tool_call) messages.append(response.message) messages.append({role: tool, content: tool_result}) return 达到最大步数限制实际用的时候max_steps这个参数很关键。设太小复杂任务完不成设太大可能陷入死循环浪费token。我的经验是简单任务设5步复杂任务设15步同时加一个超时机制超过一定时间强制结束。3.3 Agent并发处理怎么扛住高并发AI Agent怎么扛并发是最近被问得最多的问题之一。Agent和普通API不一样一次Agent调用可能涉及多轮LLM请求和多次工具调用耗时可能是普通请求的十倍甚至百倍。如果并发上来很容易把模型API打爆或者把工具服务拖垮。我的做法是分三层处理接入层限流、执行层异步、模型层排队。接入层用令牌桶算法限制并发请求数超过阈值的请求直接返回排队中执行层用异步任务队列每个Agent任务作为一个独立任务执行不阻塞主线程模型层用信号量控制同时进行的LLM调用数避免触发模型API的限流。import asyncio from asyncio import Semaphore llm_semaphore Semaphore(10) # 最多10个并发LLM调用 async def call_llm_with_limit(messages): async with llm_semaphore: return await llm.async_chat(messages)这个信号量的大小要根据模型API的限流阈值来定。比如模型API允许每分钟60次调用平均每次调用2秒那并发数大概设2-3比较合适。设太大容易触发限流设太小浪费资源。实操心得Agent并发处理最怕的不是模型限流而是工具调用超时。我建议每个工具调用都设独立的超时时间默认5秒超过就返回失败让Agent自己决定是重试还是换方案。3.4 Agent安全别让你的Agent被投毒Agent安全是个容易被忽视但极其重要的话题。最近有个研究方向叫AgentPoison讲的是通过污染Agent的记忆或知识库让Agent执行恶意操作。比如攻击者在Agent能访问的网页里埋一段恶意指令Agent读取后可能被诱导执行危险操作。防御措施有几个层面输入过滤对Agent读取的外部内容做安全检查、权限控制Agent调用工具时做权限校验敏感操作需要二次确认、输出审查Agent的输出在返回给用户前做安全过滤、记忆隔离不同用户的记忆严格隔离防止交叉污染。我自己的项目里所有涉及写操作的工具比如发邮件、改数据库都加了二次确认机制Agent调用这类工具时会先返回一个确认请求等用户确认后才真正执行。这个机制虽然增加了一步交互但避免了Agent误操作带来的严重后果。4. MCP协议工具调用的标准化尝试4.1 MCP是什么为什么需要它MCP全称Model Context Protocol是一个让LLM应用和外部工具、数据源标准化交互的协议。你可以把它理解成AI应用界的USB接口——以前每个AI应用要接工具都得自己写适配代码有了MCP之后工具提供方按MCP标准实现一次所有支持MCP的AI应用都能直接用。为什么需要MCP因为工具调用的碎片化太严重了。我做过一个项目要接五个不同的工具每个工具的API格式、认证方式、返回结构都不一样光适配就花了一周。如果这些工具都支持MCP我只需要一个MCP客户端就能全部接上工作量能减少80%。MCP的核心概念包括Server工具提供方、ClientAI应用方、Resource可访问的数据、Tool可调用的函数、Prompt预定义的提示模板。Server暴露能力Client发现并调用这些能力双方通过标准协议通信。4.2 MCP在实际项目中的接入方式实际接入MCP的时候有几种常见模式。第一种是本地MCP Server工具和AI应用在同一台机器上通过标准输入输出通信适合文件操作、本地数据库查询这类场景。第二种是远程MCP Server工具在远程服务器上通过HTTP或SSE通信适合SaaS工具、云服务这类场景。我最近在做一个项目需要让AI应用能读取本地的代码仓库、查询数据库、调用内部API。用MCP的方式我把这三个能力分别封装成三个MCP ServerAI应用通过一个MCP Client统一调用。这样做的最大好处是解耦——工具的实现和AI应用完全独立工具升级不影响AI应用AI应用换模型也不影响工具。{ mcpServers: { filesystem: { command: npx, args: [-y, modelcontextprotocol/server-filesystem, /path/to/dir] }, database: { command: python, args: [db_server.py] } } }这个配置看起来简单但实际用的时候有几个坑要注意。第一MCP Server的启动时间可能比较长建议在应用启动时就初始化好不要每次调用都启动。第二MCP Server的权限要严格控制特别是文件系统类的Server一定要限制可访问的目录范围。第三MCP Server的异常处理要做好Server挂了不能影响主应用。4.3 MCP工具流式输出到文件的实操使用MCP工具流式输出内容到文件是个很实用的场景。比如让AI应用生成一份长文档内容太长不能一次性返回需要流式写入文件。这个场景的实现要点是MCP工具要支持流式接口AI应用要能处理流式返回文件写入要处理好并发和断点续传。我实际做的时候MCP工具端用生成器逐块返回内容AI应用端用异步迭代器接收每收到一块就写入文件。关键是文件写入要用追加模式并且记录已写入的位置这样即使中途失败下次也能从断点继续。async def stream_to_file(mcp_client, tool_name, params, output_path): with open(output_path, a, encodingutf-8) as f: async for chunk in mcp_client.stream_call(tool_name, params): f.write(chunk) f.flush()这个模式在处理大文件生成、日志导出、报告生成这类场景时特别有用。实测下来比一次性生成再写入要稳定得多内存占用也小。5. 记忆管理让AI应用记住该记住的5.1 短期记忆和长期记忆的分层设计AI应用的记忆管理是个容易被低估的复杂问题。LLM本身是无状态的每次调用都是独立的但用户期望AI能记住之前的对话。这就需要在应用层实现记忆管理。我把记忆分成两层短期记忆和长期记忆。短期记忆就是当前会话的上下文直接放在messages列表里传给LLM长期记忆是跨会话的信息需要持久化存储在需要的时候检索出来注入到上下文中。短期记忆的管理相对简单就是控制上下文长度。但这里有个坑不是所有历史消息都值得保留。我的做法是保留最近N轮对话加上一个摘要。摘要用LLM生成把更早的对话压缩成一段简短描述。这样既保留了关键信息又控制了token消耗。长期记忆就复杂多了涉及存储、检索、更新三个环节。存储可以用向量数据库检索用语义相似度更新要考虑冲突处理。我一般用用户画像事实记忆的结构用户画像存偏好、习惯这类稳定信息事实记忆存具体的事件、数据这类可能变化的信息。5.2 记忆检索的时机和策略记忆检索不是越多越好。检索太多上下文被无关信息占满LLM反而抓不住重点检索太少又可能漏掉关键信息。我的策略是按需检索每次用户输入后先用一个轻量级的检索判断是否需要查长期记忆需要才查不需要就直接用短期记忆。检索的相似度阈值也很关键。设太高可能什么都检索不到设太低检索出一堆无关信息。我一般设0.7左右然后根据实际效果微调。另外检索结果要按相关性排序只取Top-K条K一般设3-5。注意记忆检索的延迟会直接影响用户体验。如果检索耗时超过500ms建议做成异步的先返回LLM的初步回答检索结果出来后再补充。5.3 记忆冲突的处理记忆冲突是个很隐蔽的问题。比如用户上周说我喜欢咖啡这周说我戒咖啡了如果两条记忆都存着检索时可能同时返回LLM就懵了。处理冲突的方式有两种时间优先新的覆盖旧的和显式标记标记旧记忆为已失效。我倾向于用时间优先加显式标记的组合。新记忆写入时先检索是否有冲突的旧记忆有的话把旧记忆标记为失效同时写入新记忆。检索时只返回有效记忆。这样既保证了信息的准确性又保留了历史记录方便追溯。6. 可观测性AI应用的黑盒怎么打开6.1 为什么AI应用特别需要可观测性传统应用出问题看日志基本能定位。AI应用出问题看日志往往一头雾水——LLM返回了一段奇怪的内容你不知道是Prompt的问题、模型的问题、还是上下文的问题。所以AI应用的可观测性不是锦上添花而是刚需。我一般从四个维度做可观测性请求链路每次请求经过了哪些环节、Prompt和响应实际发给LLM的内容和LLM返回的内容、工具调用调用了哪些工具、参数是什么、结果是什么、性能指标延迟、token消耗、成功率。这四个维度里Prompt和响应的记录最容易被忽视但恰恰是最重要的。我踩过的坑就是没有记录完整的Prompt结果线上出现奇怪输出时完全不知道当时发给LLM的到底是什么内容排查了两天才找到原因。6.2 链路追踪的实际落地链路追踪在AI应用里比传统应用更重要因为一次请求可能涉及多次LLM调用和工具调用没有链路追踪根本理不清。我一般用OpenTelemetry做标准化的链路追踪每个LLM调用、每个工具调用都作为一个Span记录输入输出和耗时。from opentelemetry import trace tracer trace.get_tracer(__name__) def call_llm(messages): with tracer.start_as_current_span(llm_call) as span: span.set_attribute(model, gpt-4) span.set_attribute(input_tokens, count_tokens(messages)) response llm.chat(messages) span.set_attribute(output_tokens, count_tokens(response)) return response这样每次请求的完整链路都能在追踪系统里看到哪个环节慢、哪个环节出错一目了然。实测下来有了链路追踪之后排查问题的效率至少提升三倍。6.3 LLM as Judge用模型评估模型AI应用的质量评估是个难题因为输出是开放性的没法用简单的断言判断对错。LLM as Judge是一种常用的方案用一个LLM来评估另一个LLM的输出质量。比如让评估模型给回答打分或者判断回答是否准确、是否相关、是否有害。这个方案有效但有几个坑要注意。第一评估模型和被评估模型最好不是同一个否则可能有偏见第二评估标准要明确最好给出评分细则第三评估结果要人工抽检不能完全信任。我一般用LLM as Judge做日常的质量监控每天抽一批请求让评估模型打分分数低的再人工复核。这样既能覆盖大量请求又能保证关键问题不被漏掉。7. 常见问题与排查技巧实录7.1 工具调用失败怎么排查工具调用失败是Agent开发中最常见的问题。排查思路是先看LLM有没有正确生成工具调用请求再看工具调用参数是否正确最后看工具执行是否成功。这三步任何一步出问题都会导致失败。我整理了一个速查表覆盖了最常见的几种情况现象可能原因排查方法解决方案LLM不调用工具Prompt没说明工具用途检查工具描述完善工具描述加示例工具参数格式错误Schema定义不清晰检查参数Schema简化Schema加类型约束工具调用超时工具执行太慢看工具执行日志加超时优化工具实现工具返回结果LLM不理解返回格式不友好检查返回内容格式化返回加说明工具调用死循环Agent陷入循环看调用历史加最大步数限制实操心得工具描述里加一两个调用示例能显著提高LLM正确调用工具的概率。这个技巧我试过很多次效果立竿见影。7.2 LLM返回格式错误怎么处理LLM返回格式错误是另一个高频问题特别是要求返回JSON的时候。LLM可能返回带markdown标记的JSON、可能返回不完整的JSON、可能返回多余的解释文字。处理方式有几种Prompt约束明确要求只返回JSON、后处理用正则提取JSON、重试格式错误时重新请求、结构化输出用模型支持的结构化输出功能。我一般组合使用这几种方式。Prompt里明确要求返回JSON同时用后处理做兜底如果后处理也失败就触发重试。重试时在Prompt里加上上次返回格式错误请严格返回JSON的提示成功率会高很多。7.3 并发场景下的资源竞争Agent并发执行时多个Agent可能同时访问同一个资源比如同一个文件、同一条数据库记录。如果不做并发控制可能出现数据覆盖、死锁等问题。我的做法是读操作不加锁写操作加锁锁的粒度尽量小只锁必要的资源。另外Agent的工具调用最好做成幂等的这样即使重复调用也不会产生副作用。比如发送邮件这个工具如果Agent重试导致发了两次用户会收到两封邮件。做成幂等的方式是加一个唯一ID服务端根据ID去重。7.4 模型切换后的兼容性问题换模型是常事但换模型后经常出现兼容性问题。不同模型的Prompt格式、工具调用格式、返回结构都可能不一样。我的经验是在模型接入层做适配业务层不感知模型差异。所有模型相关的差异都在接入层处理掉业务层只依赖统一接口。具体来说接入层要做几件事统一消息格式、统一工具调用格式、统一错误码、统一token计算方式。这样换模型的时候只需要在接入层加一个新的Provider实现业务层完全不用改。8. 架构演进从单体到分层的实际路径8.1 起步阶段别过度设计我见过太多项目一开始就搞微服务、搞消息队列、搞分布式结果三个月没上线。AI应用起步阶段最重要的是快速验证不是架构完美。我的建议是起步阶段用单体架构所有东西放一个进程里模型调用、Agent逻辑、工具调用、记忆管理都在一起。这个阶段的关键是模块化虽然物理上是一个进程但逻辑上要分层。模型接入层、Agent层、工具层、记忆层每层有清晰的接口层与层之间通过接口通信。这样后面要拆分的时候直接按层拆就行不用重构。8.2 成长阶段按瓶颈拆分当应用开始有真实用户瓶颈会逐渐显现。可能是模型调用太慢可能是工具调用太频繁可能是记忆检索太耗时。这时候按瓶颈拆分哪个环节是瓶颈就拆哪个。比如模型调用是瓶颈就把模型接入层拆成独立服务加缓存、加队列、加限流。工具调用是瓶颈就把工具层拆成独立服务加连接池、加异步处理。记忆检索是瓶颈就把记忆层拆成独立服务加索引、加缓存。拆分的时机很重要。太早拆分增加复杂度没收益太晚拆分瓶颈已经影响用户体验。我的经验是当某个环节的延迟占比超过30%或者错误率超过5%就该考虑拆分了。8.3 成熟阶段平台化当应用规模足够大多个业务线都在用AI能力时就该考虑平台化了。平台化的核心是能力复用模型接入能力、Agent编排能力、工具管理能力、记忆管理能力都做成平台服务业务线按需调用。平台化的好处是显而易见的业务线不用重复造轮子平台统一做优化和安全管控。但平台化也有代价灵活性降低业务线的特殊需求可能满足不了。所以平台化要把握好度核心能力平台化特殊需求允许业务线自定义。我自己的体会是平台化不是终点而是新的起点。平台化之后如何平衡统一和灵活、如何做多租户隔离、如何做配额管理都是新的挑战。但这些挑战是值得的因为平台化带来的效率提升是数量级的。8.4 架构演进中的技术债管理架构演进过程中技术债是不可避免的。关键是怎么管理技术债不让它积累到无法收拾。我的做法是每次架构调整都留出20%的时间还技术债。比如这次拆分模型接入层顺便把之前遗留的日志不规范问题修了把测试覆盖率提上去。另外技术债要显性化。我一般维护一个技术债清单记录每笔债的内容、影响、优先级、预计偿还时间。每次迭代规划时从清单里挑高优先级的还。这样技术债不会失控架构演进也能持续进行。9. 一些零散但重要的经验9.1 Prompt版本管理Prompt是AI应用的核心资产但很多人不重视Prompt的版本管理。我踩过的坑是改了一版Prompt效果变差了想回滚却发现旧版本没保存。后来我强制要求所有Prompt都纳入版本管理每次修改都记录变更内容和效果对比。Prompt版本管理不需要很复杂用Git管理文本文件就行。关键是要记录每次变更的效果指标比如准确率、用户满意度。这样回滚的时候有依据优化的时候有方向。9.2 Token成本控制Token成本是AI应用的主要成本之一控制不好可能一个月烧掉几万块。控制手段有几个上下文压缩用摘要代替完整历史、缓存相同请求直接返回缓存结果、模型分级简单任务用便宜模型复杂任务用贵模型、输出限制限制max_tokens。我一般会做一个成本监控面板实时看token消耗和成本。设置一个日预算超过就告警。这样能及时发现异常消耗避免月底看到账单吓一跳。9.3 测试策略AI应用的测试和传统应用不一样。传统应用可以用断言判断对错AI应用的输出是开放性的没法简单断言。我的测试策略是分三层单元测试测工具函数、测格式转换、集成测试测完整链路用固定输入验证输出在合理范围内、评估测试用LLM as Judge做质量评估。单元测试和集成测试可以自动化评估测试建议人工抽检。另外建议维护一个黄金测试集包含各种典型场景的输入和期望输出每次改动后都跑一遍确保没有回归。9.4 团队协作AI应用开发往往需要多角色协作算法工程师调模型、后端工程师搭架构、产品经理定需求、运维工程师保稳定。协作的关键是接口清晰和信息透明。接口清晰意味着各角色之间的交付物有明确格式信息透明意味着Prompt、模型配置、评估结果这些关键信息团队都能看到。我自己的团队用的是一个共享文档加一个实验记录本。共享文档记录架构设计、接口定义、部署流程实验记录本记录每次Prompt调整、模型切换、参数优化的效果。这样信息不会散落在个人手里新人也能快速上手。10. 最后聊几句实际体会做AI应用架构设计这两年最大的感受是没有银弹只有权衡。每个架构决策都有代价关键是想清楚你要什么、愿意放弃什么。追求低延迟可能要牺牲准确性追求高准确可能要增加成本追求灵活性可能要增加复杂度。另一个感受是架构是演进的不是设计出来的。一开始想得再完美实际跑起来总会遇到意想不到的问题。所以不要追求一步到位而是保持架构的可演进性遇到问题能快速调整。还有一个体会是可观测性怎么强调都不为过。AI应用的不确定性太高没有完善的可观测性出了问题就是抓瞎。我现在的项目可观测性相关的代码占比超过20%但我觉得值因为它节省的排查时间远超投入。最后分享一个小技巧每次架构调整后写一份架构决策记录记录这次调整的背景、方案、理由、影响。这份记录当时可能觉得没用但半年后回头看能帮你快速回忆起当时的思考过程避免重复踩坑。这个习惯我坚持了一年多受益匪浅。
返回列表