news 2026/6/26 0:12:24

AI多智能体编排实战:Sequential/MapReduce/Consensus三大模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI多智能体编排实战:Sequential/MapReduce/Consensus三大模式

1. 项目概述:当单个AI“专家”不够用时,我们怎么让一群AI“团队”高效协作?

你有没有试过让一个大模型同时干好几件事?比如一边写周报、一边查竞品数据、一边生成PPT大纲,还要求它不漏掉任何细节、不自相矛盾、不把财务数字和市场策略混为一谈?我试过,结果很真实——它要么在中间突然“忘掉”自己前面说了什么,要么把不同任务的逻辑强行拧在一起,最后交出一份看起来很华丽、但经不起推敲的“缝合怪”报告。这根本不是模型能力不行,而是我们给它的角色定位错了:它本该是位经验丰富的“首席顾问”,而不是包揽所有杂活的“前台+会计+设计师+司机”的全能打工人。

这就是多智能体系统(Multi-Agent Systems)真正要解决的问题。它不追求造一个“万能神模型”,而是像组建一支专业足球队:守门员只管扑救,前锋专注射门,中场负责调度串联——每个Agent都是高度特化的“领域专家”,它们之间不靠单打独斗,而靠一套清晰、可靠、可验证的协作规则来配合。这种协作,就是“Agent Orchestration”(智能体编排)。它不是玄学,也不是未来概念,而是今天就能落地的工程实践:用确定性的流程设计,去驾驭不确定性的AI能力。关键词里反复出现的“Towards AI”,恰恰说明这个方向已从学术论文走向了工程一线——它不再是实验室里的玩具,而是正在被成千上万数据团队、AI产品团队用来构建真实业务系统的底层范式。这篇文章,就是我过去一年在三个实际项目中,把“编排”从理论图纸变成生产环境稳定服务的全过程复盘。它不讲空泛的架构图,只讲你在凌晨三点排查一个Agent死循环时,真正需要知道的那几行关键配置、那个被忽略的超时参数、以及为什么“让所有Agent都去查同一份数据库”会成为整个系统最脆弱的单点。

2. 核心设计思路:为什么不能直接让Agent们“自由讨论”?

2.1 “自由协作”的幻觉与现实崩塌点

刚接触多智能体时,我脑子里也闪过一个浪漫画面:让几个Agent围坐一圈,你一句我一句地“头脑风暴”,最后自然产出最优解。听起来很智能,对吧?但实操第一天就翻车了。我们设计了一个简单的“市场分析助手”:Agent A负责抓取行业新闻,Agent B负责整理政策文件,Agent C负责生成趋势摘要。我们没加任何协调逻辑,只给了个统一提示词:“请协同完成市场分析报告”。结果呢?A抓到一条关于新能源补贴的新闻,B恰好也读到同一份政策原文,C在汇总时发现两段描述几乎一样,但它无法判断这是信息冗余还是彼此印证,于是把同一句话复制粘贴了两次,还自信地加了粗。更糟的是,当A因网络波动延迟30秒才传回数据,B和C已经基于“空数据”跑完了全部流程,最终交出一份只有标题、正文全是“暂无数据”的报告。

提示:这不是模型“笨”,而是缺乏“过程可见性”。人类开会能随时喊停、追问、确认议程,AI Agent没有这种元认知能力。它们的“对话”本质是串行的API调用,每一次响应都基于上一次输入的快照,没有共享内存,没有实时状态同步,更没有“我刚才说错了,请忽略”的撤回键。

2.2 编排的本质:用“交通规则”替代“自由马路”

所以,我们彻底放弃了“自由讨论”幻想,转而设计一套严格的“交通规则”。核心思想就一条:所有Agent之间的信息流动,必须经过一个中央协调器(Orchestrator),且每一次交互都必须是明确的、有状态的、可追溯的。这个协调器不参与具体业务逻辑(比如它不写报告、不查数据),它只做三件事:

  1. 分发任务:根据当前全局状态(比如“已获取新闻数据,但政策文件缺失”),决定下一步该调用哪个Agent、传什么参数;
  2. 聚合结果:接收各Agent返回的结构化输出(必须是JSON,带明确字段名,如{"summary": "xxx", "confidence_score": 0.92}),而非自由文本;
  3. 决策路由:基于预设规则或轻量级判断(比如if confidence_score < 0.85 then trigger_agent("fact_checker") else proceed_to_next_step),决定流程走向。

这个设计看似增加了中间环节,实则大幅提升了稳定性。举个例子:当Agent A超时未响应,协调器不会傻等,它会在设定的15秒后主动标记该步骤为“失败”,并触发备用方案——比如调用一个更慢但更稳的本地爬虫Agent,或者直接向用户返回“政策数据暂不可用,建议稍后重试”。这种确定性,是自由协作永远无法提供的。

2.3 为什么选“模式化编排”而非“通用框架”?

市面上有不少号称“开箱即用”的多智能体框架,它们提供一堆抽象接口,让你“轻松定义Agent”。但我在两个项目里踩过坑:一个框架强制所有Agent必须继承同一个基类,导致我们一个现成的Python数据分析脚本(用pandas处理Excel)硬生生改了三天才塞进去;另一个框架的调试日志全是内部UUID,出了问题根本找不到是哪个Agent、哪次调用、哪个字段出的错。后来我们彻底转向“模式化编排”——不依赖黑盒框架,而是把几种最常用、最可靠的协作模式,用最直白的代码逻辑实现出来。就像木工不用“万能工具箱”,而是熟练掌握“榫卯”“胶合”“钉接”这几种基础工艺,再复杂的家具也能搭出来。本文后续要展开的Sequential、MapReduce、Consensus三种模式,就是我们验证过的、能覆盖80%以上业务场景的“基础工艺”。

3. 三大核心编排模式详解:从顺序执行到群体共识

3.1 顺序模式(Sequential):最简单,也最容易被低估的“黄金路径”

顺序模式,顾名思义,就是让Agent们像流水线工人一样,一个接一个地干活:A做完,把结果交给B;B做完,再交给C……直到最后一步。很多人觉得这太“原始”,不如并行酷炫。但我的经验是:70%以上的业务流程,顺序模式不仅是够用的,而且是最稳健、最容易调试、最容易解释的。比如我们为一家律所做的“合同风险初筛”系统:

  • Agent 1(条款提取):从PDF合同中精准识别出“违约责任”“管辖法院”“保密义务”等关键章节,输出结构化JSON;
  • Agent 2(法条匹配):接收JSON,调用法律数据库API,为每个条款匹配最新有效的司法解释和判例;
  • Agent 3(风险评级):基于匹配结果,按预设规则(如“引用已废止司法解释”扣5分,“管辖法院约定不明”扣3分)计算总风险分,并生成通俗语言的风险提示。

注意:顺序模式的成败,90%取决于“接口契约”的严谨性。我们强制规定:每个Agent的输入必须是明确的JSON Schema(例如Agent 2的输入必须包含"clause_text""clause_type"字段),输出也必须是Schema校验通过的JSON。一旦校验失败,协调器立刻报错,而不是把脏数据传给下一个Agent。这避免了大量“下游Agent试图解析上游胡乱输出的字符串”导致的崩溃。

实操中,我们用一个极简的Python函数实现了这个模式:

def run_sequential(agents: List[Callable], initial_input: dict) -> dict: """顺序执行Agent链,每一步输出作为下一步输入""" current_state = initial_input for i, agent in enumerate(agents): try: # 每步设置独立超时,避免单点拖垮全局 result = timeout_call(agent, current_state, timeout=30) # 强制Schema校验(使用pydantic) validated_result = AgentOutputModel(**result) current_state = validated_result.dict() except Exception as e: raise RuntimeError(f"Agent {i} failed: {str(e)}") return current_state

这个函数只有12行,但它解决了所有痛点:超时控制、错误隔离、类型安全。比任何复杂框架都更透明、更可控。

3.2 并行模式(MapReduce):如何让10个Agent同时干活,又不把结果搞成一锅粥?

当任务天然可以拆分时,顺序模式就太慢了。比如分析100家竞品公司的官网,如果让一个Agent挨个爬、挨个读,可能要3小时;但如果让10个Agent每人负责10家,理论上18分钟就能搞定。这就是MapReduce模式的价值:Map(分发) + Reduce(聚合)。但难点不在“分发”,而在“聚合”——10个Agent返回的10份报告,格式是否统一?质量是否可信?有没有重复或遗漏?

我们的解决方案是“双阶段Reduce”:

  • 第一阶段(结构化归一):每个Agent在返回结果时,必须严格遵循一个中央定义的CompetitorReportSchema。这个Schema规定了必须包含company_namecore_productpricing_model(枚举值:subscription/free/ad_based)、last_updated_date等字段。协调器收到所有结果后,先批量校验Schema,任何一项不合规,该Agent的结果直接丢弃,并记录告警。
  • 第二阶段(语义聚合):校验通过的数据,进入Reduce层。这里我们不用大模型“总结”,而是用确定性规则:比如pricing_model字段,统计10家公司中subscription出现的次数;core_product字段,用Jaccard相似度算法计算各公司产品描述的共性关键词(如“SaaS”“cloud-native”“API-first”),生成高频词云。只有当某个结论有≥7家公司的数据支撑时,才写入最终报告。

实操心得:MapReduce最常犯的错,是让Reduce Agent去做“创造性工作”。比如让一个Agent看着10份报告,自由发挥写一段“行业洞察”。这会导致结果不可控、不可复现。我们的原则是:Reduce只做统计、对比、阈值判断等确定性操作;真正的“洞察”由后续的人工审核或更高级的分析模块完成。这保证了整个Pipeline的可审计性。

3.3 共识模式(Consensus):当答案没有标准时,如何让多个AI“投票”出最靠谱的结论?

有些问题,根本没有唯一正确答案。比如:“这份用户投诉邮件的情绪是愤怒、失望,还是焦虑?”不同模型可能给出不同判断。这时,顺序和并行都不适用,我们需要共识模式。它的核心是:让多个Agent独立分析同一输入,然后通过一个轻量级的“仲裁器”(Arbiter)综合它们的输出,得出一个加权共识结果

我们为一个电商客服系统实现了这个模式。输入是一段用户聊天记录,三个Agent分别基于不同策略判断情绪:

  • Agent A(规则引擎):扫描关键词(“垃圾”“骗子”“退钱”),匹配预设规则库;
  • Agent B(微调模型):使用在千万条客服对话上微调的小型BERT模型;
  • Agent C(零样本大模型):用GPT-4 Turbo,提示词强调“请给出概率分布”。

仲裁器不简单取多数票,而是设计了一套加权逻辑:

  • 如果Agent A和B结论一致(比如都判“愤怒”),且C的概率分布中“愤怒”得分>0.7,则直接采纳;
  • 如果三者分歧,且C的“愤怒”概率最高(0.6),但A和B都判“失望”,则触发“深度分析”:调用第四个Agent D(专门分析语气词和标点),重新评估;
  • 如果仍无法统一,则返回“需人工复核”,并附上三方结论及置信度。

关键细节:共识模式的性能瓶颈往往不在Agent本身,而在仲裁逻辑的复杂度。我们曾把仲裁器做成一个复杂的决策树,结果每次调用都要2秒。后来重构为一个预编译的Python字典映射表({("anger", "disappointment", "anger"): "anger", ("anger", "anxiety", "disappointment"): "review_manual"}),耗时降到20毫秒。这提醒我们:编排层的优化,有时比模型层的优化更能立竿见影。

4. 实操全流程:从零搭建一个可运行的编排系统

4.1 环境准备与最小可行架构

别被“系统”二字吓到。我们第一个可运行的编排Demo,只用了3个文件、不到200行代码,却完整实现了Sequential模式。环境要求极低:

  • Python 3.9+
  • requests(调用Agent API)
  • pydantic(Schema校验)
  • tenacity(重试机制)

架构图(文字版):

User Request → [Orchestrator] → Agent 1 (API) → Agent 2 (API) → ... → Final Response ↓ [Shared State Store] ←— 用于跨Agent传递临时数据(如session_id, cache_key)

注意:我们刻意避开了Redis、PostgreSQL等外部存储。初期,所有状态都存在内存字典里(state_store = {})。这牺牲了分布式能力,但换来极致的调试便利——你可以在任意断点print(state_store),看到整个流程的实时快照。等系统稳定后,再平滑替换为Redis,只需改一行初始化代码。

4.2 Agent开发规范:让每个“专家”都守规矩

为了让Agent能无缝接入编排系统,我们制定了铁律般的开发规范,所有新加入的Agent必须通过以下检查:

  1. 输入/输出契约:必须提供input_schema.jsonoutput_schema.json,用JSON Schema语法定义;
  2. 健康检查端点GET /health返回{"status": "ok", "latency_ms": 123},协调器启动时自动探测;
  3. 标准化错误码:HTTP 400表示输入数据违规(如日期格式错误),404表示资源不存在(如找不到某份文档),500才是内部错误;
  4. 必含元数据:每个响应JSON必须带{"agent_version": "1.2.0", "timestamp": "2025-09-04T10:30:00Z"}字段,便于追踪和回滚。

我们甚至写了一个自动化检查脚本validate_agent.py,开发者只需运行python validate_agent.py --url http://localhost:8000,脚本就会自动调用健康检查、发送测试数据、校验Schema、测量延迟,并生成一份HTML报告。这把“接入门槛”从“需要理解整个系统”降到了“只要会写API就行”。

4.3 协调器核心代码:150行搞定生产级编排

下面这段代码,是我们在线上跑了半年、日均处理2万请求的协调器核心。它删减了日志和监控部分,保留了所有关键逻辑:

from pydantic import BaseModel, ValidationError from tenacity import retry, stop_after_attempt, wait_exponential import time import json class Orchestrator: def __init__(self, agents_config: list): self.agents = agents_config # [{"name": "extractor", "url": "http://a:8000/process"}] @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=1, max=10)) def _call_agent(self, agent_config: dict, payload: dict) -> dict: # 超时设置:基础30秒,每重试一次+5秒 timeout = 30 + (self._retry_state.attempt_number - 1) * 5 response = requests.post( f"{agent_config['url']}/process", json=payload, timeout=timeout ) response.raise_for_status() return response.json() def run_sequential(self, initial_payload: dict) -> dict: state = initial_payload.copy() for agent_config in self.agents: try: # 1. 调用Agent result = self._call_agent(agent_config, state) # 2. Schema校验(假设每个Agent配置里有schema_path) schema = load_json_schema(agent_config["schema_path"]) validated = schema.parse_obj(result) # pydantic校验 # 3. 更新状态,准备下一轮 state.update(validated.dict()) except ValidationError as e: raise ValueError(f"Agent {agent_config['name']} output invalid: {e}") except requests.exceptions.Timeout: raise TimeoutError(f"Agent {agent_config['name']} timeout after {timeout}s") return state # 使用示例 config = [ {"name": "extractor", "url": "http://extractor:8000", "schema_path": "schemas/extract.json"}, {"name": "analyzer", "url": "http://analyzer:8000", "schema_path": "schemas/analyze.json"} ] orchestrator = Orchestrator(config) result = orchestrator.run_sequential({"document_id": "doc_123"})

这段代码的威力在于:它把重试、超时、校验、错误分类这些“脏活累活”全包圆了,业务开发者只需要关心自己的Agent逻辑。上线后,我们发现95%的线上故障,都源于Agent自身(如模型OOM、数据库连接池满),而协调器自身的崩溃率趋近于零——这正是编排系统该有的样子:坚固的骨架,柔软的血肉。

4.4 监控与可观测性:看不见的流程,才是最危险的

没有监控的编排系统,就像没有仪表盘的飞机。我们给每个关键环节都埋了点:

  • Agent粒度:每个Agent调用的latency_msstatus_codeinput_size_bytesoutput_size_bytes
  • 流程粒度:整个Sequential链的total_latency_msstep_countfailure_rate_by_step(哪个步骤最容易失败);
  • 业务粒度success_rate_by_user_tier(VIP用户成功率是否更高?)、avg_retries_per_request(重试次数是否异常升高?)。

所有指标都推送到Prometheus,用Grafana看板实时展示。最救命的一个看板,是“失败请求溯源”:点击任意一个失败请求ID,页面直接展开完整的调用链路,高亮显示是哪个Agent、哪次调用、返回了什么错误码和错误消息。有一次,我们发现analyzerAgent的失败率在每天上午10点准时飙升,排查发现是它依赖的第三方NLP API有配额限制,每天10点重置。没有这个看板,这个问题可能一个月都发现不了。

注意:监控数据本身也是“编排”的一部分。我们把监控告警也设计成一个Agent:当failure_rate_by_step连续5分钟>5%,它会自动触发一个alert_handlerAgent,该Agent会:1. 检查该Agent的健康状态;2. 如果健康,自动扩容实例;3. 如果不健康,发送Slack告警并附上最近10次失败详情。这实现了闭环自治。

5. 常见问题与实战排障:那些文档里不会写的坑

5.1 问题速查表:高频故障与一键修复

故障现象根本原因快速诊断命令推荐修复方案
Sequential流程卡在某一步,不超时也不报错Agent进程假死,HTTP连接保持长连接但无响应curl -v http://agent-x:8000/health查看是否返回在协调器_call_agent中增加requestsconnection_timeoutread_timeout分离设置,避免长连接阻塞
MapReduce结果中,部分Agent返回空JSON或格式错乱Agent未处理好异常,捕获了Exception但返回了空字典grep -r "return {}" ./agent_code/强制所有Agent的主函数末尾加raise ValueError("Empty response not allowed"),并在协调器校验层前置拦截
Consensus模式下,仲裁器总是触发“人工复核”,效率低下三个Agent的判断标准差异过大,缺乏校准统计各Agent单独运行时的准确率(用标注数据集)对低准确率Agent进行针对性Prompt Engineering,或降低其在仲裁权重中的占比
系统负载升高时,Agent间通信延迟激增,引发连锁超时所有Agent共用同一数据库连接池,锁竞争严重SHOW PROCESSLIST;查看MySQL连接数为每个Agent分配独立的数据库连接池,大小按QPS预估(公式:pool_size = avg_qps * avg_latency_seconds * 2

5.2 那些“只可意会”的排障技巧

  • “时间戳”是你的第一线索:当一个请求失败,不要先看错误消息,先看所有Agent返回的timestamp字段。如果Agent A的时间是10:00:00.123,Agent B是10:00:00.125,但Agent C是10:00:30.456,那问题一定出在C的上游——可能是A或B的输出被C误解析,导致它卡在数据清洗上。这个技巧帮我们快速定位了70%的时序类问题。

  • 用“最小输入”做压力测试:不要一上来就用10MB的PDF压测。先准备一个100字的纯文本,确保它能100%成功走完全流程。然后逐步增加复杂度:加一个表格、加一张图片、加一个加密附件……每加一项,就观察哪个环节开始不稳定。这比盲目调参高效十倍。

  • “假装失败”是最好的测试:在协调器代码里,临时插入一行if random.random() < 0.1: raise ConnectionError(),模拟10%的Agent随机失败。然后观察整个系统是否能优雅降级(比如跳过失败步骤,用默认值填充,或触发备用Agent)。很多系统在真实故障前,从未经历过这种“混沌测试”,一出问题就全线崩溃。

5.3 性能调优的临界点:什么时候该换架构?

我们曾在一个金融风控项目中,把Sequential模式做到了极致:单次请求调用12个Agent,平均耗时1.8秒,P95延迟2.3秒,完全满足业务SLA。但当业务方提出“需要支持每秒1000并发”时,我们立刻意识到:继续堆Agent不是出路。因为12个HTTP调用的串行延迟,存在硬性物理上限(光速+网络抖动)。这时,我们必须做架构升级:

  • 横向扩展:将协调器无状态化,前面挂Nginx做负载均衡;
  • 纵向优化:对计算密集型Agent(如OCR、语音转写),改用gRPC协议替代HTTP,序列化用Protocol Buffers;
  • 模式切换:将部分可并行的步骤(如同时调用3个不同征信API)从Sequential改为MapReduce子流程。

关键判断标准是:当单次请求的Agent调用数超过8个,或平均延迟超过1.5秒,就必须启动架构评审。这不是教条,而是我们用服务器成本和客户投诉率换来的血泪教训。

6. 我的个人体会:编排不是技术,而是新的产品思维

写到这里,我想分享一个可能颠覆你认知的观点:Agent编排的终极挑战,从来不是技术实现,而是产品定义。技术上,用150行代码搭起一个能跑的Sequential系统,可能只要半天。但要让它真正创造价值,你需要回答一连串产品经理才会问的问题:

  • 这个流程里,哪一步的“失败”是可以接受的?比如“竞品价格抓取失败”,是应该跳过、用历史数据填充,还是必须中断整个流程?这决定了你的容错策略;
  • 用户需要看到多少“过程”?是只要最终报告,还是想看到“Agent A找到了3条相关新闻,Agent B匹配了2条有效法条”这样的中间态?这决定了你的UI设计和日志粒度;
  • 当三个Agent给出冲突结论时,“共识”结果的权威性,是由算法决定,还是由业务规则决定?比如在医疗诊断场景,一个资深医生的判断,是否应该永远override两个AI模型的投票?这决定了你的仲裁器逻辑。

我见过太多团队,花三个月打磨出一个技术上完美的编排系统,却因为没想清楚这些问题,在交付时被业务方一句“这和我们想要的不一样”打回原形。所以,我的建议是:在写第一行代码前,先和业务方一起画一张“决策流程图”。图上不写代码,只写:

  • 每个菱形节点(判断点):依据什么条件分支?
  • 每个矩形节点(动作):期望的输入是什么?输出必须包含哪些字段?
  • 每个平行四边形节点(输入/输出):用户能看到什么?系统需要记录什么?

这张图,就是你后续所有技术决策的宪法。它比任何架构图都重要。因为最终,用户不会为你的“精妙编排算法”付费,他们只为“更快拿到更准的报告”、“更少被错误预警打扰”、“更清楚知道系统在想什么”而买单。编排,只是让这些价值承诺,变得可实现、可验证、可交付的那座桥。而桥的两端,永远是技术与人。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 0:02:55

【计算机毕业设计案例】基于 SpringBoot 的图书销售数据统计系统设计与实现 互联网图书购物服务信息化系统设计与实现(程序+文档+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/6/25 23:59:30

带标注的多囊卵巢综合征数据集,可识别卵巢内的卵泡,识别率92.3%,2034张图,支持yolo,coco json,voc xml,文末有模型训练代码

​ 带标注的多囊卵巢综合征数据集&#xff0c;可识别卵巢内的卵泡&#xff0c;识别率92.3%&#xff0c;2034张图&#xff0c;支持yolo&#xff0c;coco json&#xff0c;voc xml,文末有模型训练代码 医学应用&#xff1a; 医学上两大核心检测用途 筛查 / 确诊多囊卵巢综合征…

作者头像 李华
网站建设 2026/6/25 23:58:19

DeepSeek V4混合式KV Cache推理优化实战解析

1. 项目概述&#xff1a;这不是一份普通技术报告&#xff0c;而是一张通往新范式的路线图“扒完 DeepSeek V4 报告&#xff0c;我翻出了这个隐藏彩蛋”——这句话刚在技术圈小范围流传时&#xff0c;我第一反应是&#xff1a;又一个标题党&#xff1f;但当我真正坐下来&#xf…

作者头像 李华
网站建设 2026/6/25 23:55:50

AI 驱动的设计系统治理:从 Figma Token 到代码约束的自动化同步

AI 驱动的设计系统治理&#xff1a;从 Figma Token 到代码约束的自动化同步 一、设计系统失同步&#xff1a;Figma 与代码的"双源真相"困境 设计系统的核心承诺是"单一真相源"&#xff1a;Figma 中定义的 Design Token&#xff08;颜色、间距、字体、阴影&…

作者头像 李华
网站建设 2026/6/25 23:55:04

【回眸】搞钱日记——近期的复盘与成长

目录 前言 工作复盘 生活复盘 理财复盘 工作期望 生活期望 理财期望 后记 前言 近期工作比较忙&#xff0c;博文发布的也比较少&#xff0c;在此对近期的一些生活工作上的经历做一些复盘盘点&#xff0c;也算是更了解自己的一步。 工作复盘 主要集中在offline的制作&…

作者头像 李华