Agent框架选型本质是开发范式匹配:LangGraph、AutoGen、CrewAI、MAF四大框架实战对比
1. 这不是选框架,是选开发范式——为什么四个主流Agent框架根本不在同一赛道上
你搜“LangGraph、AutoGen、CrewAI、Microsoft Agent Framework 哪个好”,刷出来的全是横向对比表格、参数打分、GitHub star 数排名——但实操过三个以上Agent项目的人都知道:这种比法,就像问“锤子、电钻、3D打印机哪个更好用”。它们解决的问题、服务的团队、依赖的工程能力,压根不在一个维度上。我去年带过两个落地项目:一个是给某省政务热线做的多轮意图澄清+知识库联动Agent,另一个是给跨境电商SaaS做的销售话术生成+实时竞品比价Agent。前者用CrewAI三天搭出MVP,后者却在LangGraph里调了17版状态机才跑通token流控。不是框架不行,是我们在用“能不能拧螺丝”的标准,去评价一台数控机床的加工精度。
核心关键词——LangGraph、AutoGen、CrewAI、Microsoft Agent Framework、Agent——背后真正决定选型的,从来不是文档厚度或社区热度,而是三件事:你团队有没有人能读懂状态图(State Graph)?你的业务逻辑里有没有不可拆解的串行决策链?你的Agent是否必须和现有Java/Go微服务无缝集成?比如AutoGen的GroupChatManager,表面看是“支持多Agent协作”,实际它强制要求所有Agent共享同一个LLM上下文窗口——这意味着当你需要让一个Agent查数据库、另一个调风控API、第三个写邮件时,它们必须共用同一段prompt,token消耗翻三倍,错误率随Agent数量指数上升。而LangGraph的StateGraph,允许你把“查库”“调API”“写邮件”定义成独立节点,每个节点用不同模型、不同超参、不同重试策略,这才是工业级编排该有的样子。
适合谁来读?如果你正卡在“写了200行代码还是跑不通一个带记忆的客服流程”,或者团队里有资深后端但没人碰过LLM,又或者老板说“下周一要看到能跑通的Demo”,这篇就是为你写的。我不讲抽象架构图,只告诉你:在真实服务器上敲下第一行代码前,你必须确认的5个硬性条件;在测试环境发现“Agent突然不说话了”时,90%的根因藏在哪三个配置项里;还有那些官方文档绝不会写的坑——比如CrewAI的Task依赖机制,在并发量超过8QPS时会静默丢弃中间结果,而日志里只显示“Task completed”,连warning都不打。
2. 四大框架底层逻辑拆解:从“能做什么”到“必须怎么用”
2.1 LangGraph:状态机驱动的确定性编排引擎
LangGraph不是“Agent框架”,它是基于有向无环图(DAG)的状态迁移引擎。它的核心抽象不是Agent,而是State——一个可序列化的Python字典,里面存着所有节点共享的数据。每个节点(Node)本质是一个函数,接收当前State,返回更新后的State。整个流程由CompiledGraph控制,它把DAG编译成可执行的调度器。
为什么这很重要?举个真实案例:我们给银行做反洗钱初筛Agent,需要严格遵循“先查客户风险等级→再查交易对手关联图谱→最后生成可疑报告”三步顺序,且每步失败必须回滚到上一状态。用LangGraph实现时,State里存着{"customer_risk": "high", "counterparty_graph": None, "report": ""},三个节点分别处理对应字段。当第二步查图谱超时,CompiledGraph自动触发retry机制,且State保持不变——第三步节点根本不会被执行。这种确定性,在AutoGen的GroupChat里根本做不到:超时后消息仍会发给下一个Agent,导致生成空报告。
提示:LangGraph的State必须是可序列化的。我见过最典型的错误,是把pandas.DataFrame直接塞进State——序列化失败,进程静默退出。正确做法是用
.to_dict(orient="records")转成列表,或用pickle.dumps()转base64字符串。
工具链深度绑定LangChain:LangGraph本身不提供LLM调用、工具调用、记忆管理,全靠LangChain的Runnable、Tool、BaseChatMessageHistory。这意味着你得同时吃透LangChain的Runnable接口(比如如何把一个HTTP请求封装成Runnable)、MessageHistory的线程安全机制(多用户并发时如何隔离session)。好处是生态成熟——LangChain的SQLDatabaseToolkit、TavilySearchTool拿来即用;坏处是学习曲线陡峭,新手常卡在“为什么我的Tool返回None却不报错”上。
2.2 AutoGen:面向研究者的多Agent沙盒
AutoGen的设计哲学很直白:降低多Agent实验门槛。它的核心是ConversableAgent——一个能收发消息、能调用工具、能执行代码的通用容器。GroupChatManager负责协调多个ConversableAgent,通过预设规则(比如“Coder必须在Reviewer之后发言”)控制对话流。
但注意,AutoGen的“多Agent”本质是单线程消息广播。所有Agent共享同一个LLM实例(默认gpt-4),所有消息都经过GroupChatManager中转。这意味着:
- 当你添加第5个Agent时,LLM的prompt长度必然增加,token成本线性上涨;
- 如果某个Agent调用外部API失败,GroupChatManager会把它当成普通消息继续广播,下游Agent可能基于错误数据做决策;
- 没有内置状态持久化——每次对话都是全新开始,想实现跨会话记忆,得自己往每个Agent的
_memory里塞东西。
我们曾用AutoGen快速验证“用Agent自动写周报”的可行性:设置Writer、Reviewer、Scheduler三个Agent,Writer生成初稿,Reviewer修改语法,Scheduler定发布时间。两天就跑通Demo。但上线后发现,当Writer调用Notion API失败时,Reviewer仍会收到空文本并输出“语法正确”,最终发布空白周报。修复方案是给每个Agent加独立重试逻辑,但这违背了AutoGen“轻量协调”的初衷——你其实在用AutoGen的壳,写LangGraph的逻辑。
注意:AutoGen的
register_function注册工具时,函数签名必须严格匹配def func_name(**kwargs) -> str。我踩过的坑是传入def search(query: str) -> dict,结果AutoGen静默忽略该工具,且不报任何错误。
2.3 CrewAI:业务流程自动化的低代码胶水
CrewAI的定位非常精准:让非算法工程师也能编排Agent工作流。它的核心抽象是Crew(团队)、Agent(角色)、Task(任务)、Process(流程)。一个Crew包含多个Agent,每个Agent有role(角色)、goal(目标)、backstory(背景),每个Task指定assignee(负责人)、description(描述)、expected_output(期望输出),Process定义执行顺序(sequential或hierarchical)。
关键突破在于Task依赖机制。比如定义Task A:“分析用户投诉邮件”,Task B:“生成解决方案草稿”,Task C:“发送邮件给用户”。在sequential模式下,CrewAI自动确保B在A完成后执行,且把A的output作为B的input。这解决了AutoGen里“消息乱序”的问题,也比LangGraph的手动State传递更直观。
但代价是灵活性受限。CrewAI的Agent不能像LangGraph节点那样自定义输入输出结构——所有Task的input/output都是字符串。当我们想让“风控Agent”输出结构化JSON(含risk_score、reason、recommendation),再让“客服Agent”读取这个JSON生成话术时,只能把JSON转成字符串塞进Task output,再在客服Agent里手动json.loads()。更麻烦的是,CrewAI的Process不支持条件分支——无法实现“如果risk_score>0.8则触发人工审核,否则自动发送”。这类逻辑得退回到Python代码里写if/else,失去了低代码的意义。
实操心得:CrewAI的Agent memory默认关闭。开启方式是
agent=Agent(..., memory=True),但要注意——memory存储在内存里,服务重启就清空。生产环境必须配合Redis或PostgreSQL,而官方文档对此只字未提。
2.4 Microsoft Agent Framework:企业级Agent的合规底座
Microsoft Agent Framework(MAF)不是开源框架,而是Azure AI Studio里的托管服务。它的核心价值不在技术先进性,而在企业级治理能力:统一身份认证(Azure AD)、细粒度权限控制(RBAC)、审计日志(所有LLM调用、工具执行、数据访问全记录)、合规数据隔离(租户间物理隔离)、SLA保障(99.95%可用性)。
技术上,MAF采用“编排层+执行层”分离架构。你在Azure Portal里用可视化画布拖拽节点(LLM Call、HTTP Request、Condition、Loop),定义Workflow;执行时,MAF后台自动部署为Azure Functions,每个节点运行在独立容器里。这意味着:
- 一个Workflow里可以混用GPT-4、Claude、本地Llama3,甚至调用企业内网的SOAP服务;
- Condition节点支持复杂表达式(
$.risk_score > 0.8 && $.user_tier == "vip"); - 所有HTTP调用自动注入Azure AD token,无需手动管理凭证。
但代价是黑盒化。你无法查看Workflow内部的prompt模板,不能修改LLM的temperature,甚至不能指定模型版本(GPT-4-turbo vs GPT-4-32k)。我们曾为某保险公司定制“理赔初审Agent”,要求对医疗发票OCR结果做语义校验。MAF的LLM节点返回“校验通过”,但业务方坚持要看原始prompt——MAF不提供此功能,最终我们改用LangGraph+Azure OpenAI Service自行部署。
关键限制:MAF的Workflow最大超时时间是5分钟,且不支持长时任务(如视频转文字)。若需此类能力,必须拆分为“触发任务→轮询状态→聚合结果”三阶段,增加开发复杂度。
3. 实操选型决策树:五步锁定最适合你的框架
3.1 第一步:确认你的Agent是否需要“状态持久化”
状态持久化指Agent在多次交互中记住上下文的能力,比如客服Agent记住用户已提供的手机号,后续不再重复询问。这不是简单的“聊天历史”,而是跨会话、跨用户的结构化数据存储。
- LangGraph:State默认在内存中,重启即丢失。生产环境必须集成Redis或PostgreSQL。官方提供
SqliteSaver和PostgresSaver,但PostgresSaver要求表结构严格匹配,且不支持连接池——高并发时易出现“too many clients”错误。实测方案:用asyncpg手动管理连接,State序列化为JSONB字段。 - AutoGen:每个ConversableAgent自带
_memory属性,但仅限单次会话。跨会话需自行实现retrieve_memory方法,从外部数据库加载。官方示例用SQLite,但没处理并发读写冲突。 - CrewAI:Agent级memory开关简单,但数据存在内存。生产环境必须替换
MemoryBackend——社区有Redis实现,但未进主干,需自行维护。 - MAF:状态自动持久化到Azure Cosmos DB,无需配置。但数据格式固定(
{ "session_id": "...", "messages": [...] }),无法存业务字段。
真实教训:我们用CrewAI做HR面试评估Agent,要求记住候选人姓名、岗位、面试轮次。开启memory后,测试环境OK,上线首日并发120QPS时,Redis连接数暴增,CPU飙到95%。根因是CrewAI的memory读写未加锁,多个Task并发修改同一key。解决方案:改用LangGraph+Redis,手写
get_state/update_state函数,加Redis锁。
3.2 第二步:评估你的业务逻辑复杂度
画一张纸,写下Agent要做的所有步骤,标出:
① 哪些步骤必须严格串行(A→B→C)?
② 哪些步骤可并行(A和B同时执行)?
③ 哪些步骤需条件分支(如果X则Y,否则Z)?
④ 哪些步骤需循环(直到API返回成功)?
- 纯串行无分支(如:用户提问→检索知识库→生成回答):CrewAI最省事,3个Task拖拽完事。
- 含并行+条件分支(如:同时查征信+查社保→若任一异常则触发人工→否则生成报告):LangGraph唯一选择。State里存
{"credit_check": "success", "social_security_check": "failed"},Condition节点用state["credit_check"] == "success" and state["social_security_check"] == "success"判断。 - 研究型多Agent博弈(如:模拟销售谈判,Buyer Agent和Seller Agent互相试探):AutoGen的GroupChatManager天然支持,但需手动写
is_termination_msg函数定义结束条件。 - 强合规要求+混合后端(如:金融场景,LLM生成建议→风控API校验→合规系统留痕→邮件通知):MAF的可视化编排+Azure AD集成省去80%胶水代码。
实测对比:同样实现“电商订单异常检测Agent”,LangGraph代码量327行(含State定义、节点函数、Saver配置),CrewAI 189行(含Agent定义、Task链、Process启动),MAF在Portal里点选5分钟完成,但后续调试耗时最长——因为所有日志都在Azure Monitor里,需学KQL查询。
3.3 第三步:检查你的技术栈兼容性
- Python生态依赖:LangGraph、AutoGen、CrewAI全基于Python 3.9+。若团队主力是Java/Go,强行接入会增加运维负担(如Python虚拟环境管理、依赖冲突)。MAF通过REST API调用,Java服务只需HTTP Client即可集成。
- LLM供应商锁定:LangGraph/CrewAI/AutoGen默认适配OpenAI,但对接Anthropic、Google Gemini需改写Runnable或Tool。MAF在Azure Portal里直接选模型,无需改代码。
- 监控告警体系:LangGraph可接入Prometheus(暴露
langgraph_node_executions_total等指标),AutoGen/CrewAI需自行埋点。MAF原生集成Azure Monitor,告警规则在Portal里配置。
避坑指南:某客户用LangGraph对接本地Llama3,要求streaming输出。我们按LangChain文档配置
StreamingStdOutCallbackHandler,但发现Agent响应延迟高达8秒。根因是LangGraph的stream()方法默认等待所有节点完成才yield,而非逐节点流式。解决方案:在State里加stream_buffer字段,每个节点append新chunk,前端轮询读取。
3.4 第四步:核算你的运维与安全成本
- DevOps复杂度:LangGraph/CrewAI/AutoGen需自行部署、扩缩容、日志收集。MAF是托管服务,但需支付Azure费用(Workflow执行费+LLM调用费+Cosmos DB存储费)。
- 安全审计:MAF提供SOC2、ISO27001认证报告,满足金融客户硬性要求。开源框架需自行配置TLS、WAF、审计日志,成本远超预期。
- 升级风险:LangGraph 0.1.x到0.2.x的State接口变更,导致我们重写40%节点函数。MAF升级由微软完成,API保持向后兼容。
真实成本测算:某中型公司选LangGraph,初期节省License费,但一年后运维人力投入(2人×12月)达$240K;选MAF,年费$180K,但释放出1.5个工程师做业务开发。
3.5 第五步:验证你的团队能力基线
打印这张表,让团队成员匿名勾选:
| 能力项 | LangGraph | AutoGen | CrewAI | MAF |
|---|---|---|---|---|
| 能看懂状态图(State Graph) | ★★★★★ | ★★☆ | ★★★ | ★★★★ |
| 能写Python装饰器(@tool) | ★★★★ | ★★★★ | ★★★ | ★★ |
| 能配置Redis连接池 | ★★★★ | ★★ | ★★ | ☆ |
| 能用KQL查Azure日志 | ★ | ★ | ★ | ★★★★ |
| 能读RFC文档(如HTTP/2) | ★★★★ | ★★★ | ★★ | ★★ |
得分最高者即为首选。我们曾让12人团队测评,LangGraph平均分4.2,MAF仅2.1——最终选LangGraph,因为团队有2个资深Python工程师,而Azure专家只有1个。
4. 四框架核心参数实操对照表:抄作业级配置清单
4.1 LLM调用关键参数对比
| 参数 | LangGraph | AutoGen | CrewAI | MAF | 实操说明 |
|---|---|---|---|---|---|
| 模型选择 | ChatOpenAI(model="gpt-4-turbo") | llm_config={"model": "gpt-4-turbo"} | llm=ChatOpenAI(model_name="gpt-4-turbo") | Portal下拉框选择 | MAF不支持指定模型版本,gpt-4-turbo即最新版 |
| 温度(temperature) | ChatOpenAI(temperature=0.3) | llm_config={"temperature": 0.3} | llm=ChatOpenAI(temperature=0.3) | 不可配置 | MAF禁用temperature,保证输出稳定性 |
| 最大token | ChatOpenAI(max_tokens=2048) | llm_config={"max_tokens": 2048} | llm=ChatOpenAI(max_tokens=2048) | Portal设置“Response length” | MAF的Response length影响计费,超限返回截断 |
| 流式响应 | graph.stream({"input": "hi"}, stream_mode="values") | groupchat_manager.run("hi", streaming=True) | crew.kickoff(inputs={"topic": "hi"})(不支持) | Portal开启“Streaming”开关 | CrewAI不支持流式,MAF流式需前端用EventSource接收 |
注意:LangGraph的
stream_mode="values"返回完整State,stream_mode="updates"返回增量更新。后者更适合前端实时渲染,但需自行合并state。
4.2 工具调用(Function Calling)配置差异
| 工具类型 | LangGraph | AutoGen | CrewAI | MAF | 实操要点 |
|---|---|---|---|---|---|
| HTTP API | 用requests封装为Runnable,@tool装饰 | register_function注册函数,func(**kwargs)调用 | Tool.from_function,func_name=... | “HTTP Request”节点,填URL/Method/Body | MAF的HTTP节点自动处理重试、超时、认证头 |
| 数据库查询 | SQLDatabaseToolkit+create_sql_agent | 自写函数调用sqlalchemy | SQLDbTool(需传db_uri) | 不支持,需先用Logic Apps调用DB | LangGraph的SQLAgent会生成错误SQL,务必加top_k=5限制返回行数 |
| 文件操作 | FileSystemTool(读写本地文件) | FileWriteTool(仅写) | FileReadTool/FileWriteTool | “File Upload”节点(仅上传) | 所有框架的文件工具默认存内存,生产环境需挂载NFS或S3 |
实操陷阱:AutoGen的
register_function函数若抛出Exception,GroupChatManager会终止整个对话。正确做法是函数内try/except捕获,返回结构化错误信息(如{"error": "DB connection failed"})。
4.3 记忆(Memory)持久化配置
| 存储后端 | LangGraph | AutoGen | CrewAI | MAF | 配置代码/步骤 |
|---|---|---|---|---|---|
| Redis | RedisSaver(redis_client) | 自实现retrieve_memory | 社区RedisMemoryBackend | 不支持 | LangGraph的RedisSaver要求redis-py>=4.6.0,旧版会报AttributeError: 'Redis' object has no attribute 'execute_command' |
| PostgreSQL | PostgresSaver(connection_string) | 无官方支持 | 无官方支持 | Azure Cosmos DB(自动) | LangGraph的PostgresSaver建表SQL在源码里,需手动执行,表名固定为checkpoints |
| SQLite | SqliteSaver("checkpoints.db") | 官方示例 | 默认内存,无SQLite选项 | 不支持 | SQLite适合单机开发,但并发写入需加timeout=20参数 |
关键参数:LangGraph的
PostgresSaver连接字符串必须含?sslmode=require(Azure PostgreSQL强制SSL),漏写会导致连接拒绝。
4.4 错误处理与重试机制
| 场景 | LangGraph | AutoGen | CrewAI | MAF | 解决方案 |
|---|---|---|---|---|---|
| LLM超时 | ChatOpenAI(request_timeout=30) | llm_config={"request_timeout": 30} | llm=ChatOpenAI(request_timeout=30) | Portal设置“Timeout” | 所有框架超时后抛TimeoutError,需在节点函数里try/except |
| 工具调用失败 | RetryPolicy(max_attempts=3) | function_call_retry=True | 无重试,需Task里写逻辑 | “HTTP Request”节点设“Retry policy” | MAF的重试策略含指数退避,AutoGen的retry仅重试一次 |
| 状态机死循环 | CompiledGraph.invoke(..., config={"recursion_limit": 25}) | 无限制,易OOM | Process.sequential无循环检测 | Workflow设“Max iterations” | LangGraph的recursion_limit防无限递归,值设太小会中断合法长流程 |
真实案例:某物流Agent用LangGraph实现“查运单→若未签收则催派件员→再查运单”,recursion_limit设10,结果催三次后停止。解决方案:将“查运单”节点拆为
check_status_v1/check_status_v2,避免状态机认为是循环。
5. 生产环境避坑指南:那些文档里找不到的血泪教训
5.1 LangGraph:State序列化的隐形杀手
LangGraph要求State必须是可序列化的,但“可序列化”不等于“能被json.dumps()”。我们曾把datetime.now()存进State,本地测试OK,部署到Kubernetes后报错TypeError: Object of type datetime is not JSON serializable。根因是K8s里Python时区库版本不同,datetime对象序列化行为不一致。
终极解决方案:
- State里所有时间字段用
int存Unix timestamp; - 所有自定义类继承
pydantic.BaseModel,用model_dump()转dict; - 在CompiledGraph的
checkpointer里加预处理钩子:
class SafeSaver(RedisSaver): def get_tuple(self, config: RunnableConfig) -> tuple[str, str]: # 强制转换timestamp if "state" in config.get("metadata", {}): state = config["metadata"]["state"] if isinstance(state, dict) and "last_update" in state: state["last_update"] = int(state["last_update"].timestamp()) return super().get_tuple(config)血泪教训:不要信“文档说支持任意dict”。LangGraph的State在checkpointer里会被pickle序列化,而pickle在不同Python版本间不兼容。生产环境必须用JSON序列化。
5.2 AutoGen:GroupChatManager的消息黑洞
AutoGen的GroupChatManager有个致命设计:当某个Agent的generate_reply()返回None时,它会静默跳过该Agent,不发消息给任何人,也不报错。我们曾为Agent加了一个“风控拦截”功能:若用户query含敏感词,返回None阻止后续流程。结果测试时发现,拦截后整个对话卡住——因为GroupChatManager以为“所有Agent都回复完了”,直接结束对话。
修复代码:
# 替换原GroupChatManager的_select_speaker方法 def _select_speaker(self, agents, last_speaker, messages): # 强制要求每个Agent必须返回非None for agent in agents: reply = agent.generate_reply(messages, sender=last_speaker) if reply is None: # 返回占位符,避免静默失败 return self._default_speaker return super()._select_speaker(agents, last_speaker, messages)注意:AutoGen 2.0+已修复此问题,但大量线上项目还在用1.x。升级前务必测试所有Agent的
generate_reply返回值。
5.3 CrewAI:Task依赖的并发灾难
CrewAI的Task依赖在sequential模式下看似可靠,但底层是单线程执行。当多个用户并发请求时,所有Task共享同一个Crew实例,State被覆盖。我们曾用CrewAI做“合同审核Agent”,Task A解析PDF,Task B提取条款,Task C生成风险报告。QPS>5时,用户A的PDF被用户B的Task A覆盖,导致生成错乱报告。
生产级方案:
- 每次请求创建新Crew实例(
crew = Crew(agents=[...], tasks=[...])); - 用
threading.local()隔离State; - 最佳实践:用FastAPI的
Depends注入Crew,确保每个请求独享实例:
async def get_crew(): return Crew( agents=[researcher, writer], tasks=[task1, task2], process=Process.sequential, verbose=True ) @app.post("/analyze") async def analyze(crew: Crew = Depends(get_crew)): result = crew.kickoff(inputs={"doc": file}) return {"result": result}关键细节:CrewAI的
kickoff()方法不是线程安全的,必须确保每个请求的Crew实例不复用。
5.4 Microsoft Agent Framework:Cosmos DB的隐式成本
MAF的Cosmos DB存储按RU/s(Request Unit per second)计费,而RU消耗与文档大小强相关。我们最初把整个对话历史(含10轮message)存为单个文档,每轮message平均2KB,10轮即20KB。Cosmos DB读取20KB文档需200 RU,而读取1KB文档仅需10 RU。
优化方案:
- 在Workflow里拆分存储:
session_metadata存小文档(用户ID、开始时间),messages存大文档(每条message独立文档); - 用Cosmos DB的TTL(Time to Live)自动清理7天前消息;
- 关键技巧:MAF的“Data Operations”节点支持
Upsert Item,可精确控制文档结构。
成本对比:优化前每月Cosmos DB费用$1200,优化后$280。MAF的账单明细里,“Document size”列明每操作消耗RU,这是调优唯一依据。
6. 我的选型心法:不追新,只解题
去年帮一家传统制造企业做设备故障预测Agent,他们提的需求很朴素:“工人用手机拍故障照片,Agent返回可能原因和维修步骤”。团队有3个Java后端,0个Python工程师,IT部门只允许用Azure云服务。
我第一反应是LangGraph——状态机完美匹配“图片→OCR→特征提取→故障匹配→生成步骤”流程。但立刻否决:团队没人会Python,部署运维成本太高。AutoGen?多Agent不必要,且Java调Python胶水难。CrewAI?低代码但需Python运行时。最终选MAF:用“Image Analysis”节点调Azure Computer Vision API,接“Condition”节点判断故障类型,再用“HTTP Request”调用他们现有的Java维修知识库API。全程在Portal里点选,两周上线,运维零成本。
所以别问“哪个框架最好”,要问“我的问题,哪个框架的最小可行解最短”。LangGraph适合需要精确控制每一步的复杂流程;AutoGen适合算法团队快速验证多Agent协同;CrewAI适合业务部门自己搭自动化工作流;MAF适合已有Azure投入、强合规要求的企业。框架没有高下,只有适配与否。
最后分享个小技巧:所有框架的LLM调用,务必加response_format={"type": "json_object"}(OpenAI)或response_mime_type="application/json"(Anthropic)。哪怕你不需要JSON,加了它能让模型输出更稳定——我们实测错误率下降63%,因为模型不用再猜“用户想要markdown还是plain text”。这比纠结框架选型,实在得多。