拓冰建站拓冰建站
首页 / 资讯中心 / 正文

OpenMontage:面向多Agent协同的剧本驱动编排框架

1. 项目概述OpenMontage 不是视频剪辑软件而是一套面向 AI 智能体Agent工作流的“导演级”编排框架OpenMontage 这个名字乍一听容易让人联想到 OpenShot 或 DaVinci Resolve 那类开源视频编辑工具——毕竟 “Montage” 在影视行业里专指镜头组接、叙事重构。但实际翻遍 GitHub 仓库、官方文档和社区讨论你会发现它压根不处理帧、不渲染 H.264、也不拖拽时间线。它的核心使命是解决当前 AI Agent 开发中最棘手的“导演失语症”当一个复杂任务比如“为新产品写一份包含技术参数、竞品对比、用户痛点分析的完整白皮书并配三张信息图”被抛给多个专业 Agent技术文档 Agent、市场分析 Agent、图表生成 Agent时谁来决定先让谁干活谁来判断技术参数是否足够支撑竞品对比谁来拦截一张明显偏离主题的信息图并要求重绘OpenMontage 就是那个坐在导播台前、手握通话器、实时调度所有“演员”Agent的导演系统。它不替代 LangChain 的链式调用也不取代 LangGraph 的状态机而是站在更高一层把 Agent 当作可插拔的“功能模块”用声明式配置定义它们之间的协作逻辑、数据流转规则和异常熔断策略。我第一次在客户现场部署它时就是为了解决一个典型场景销售团队每天要生成 200 份定制化方案原来靠三个独立 Agent 轮询执行结果经常出现“图表 Agent 已开始画图但技术参数 Agent 还卡在 API 限流里”的死锁。引入 OpenMontage 后我们用不到 50 行 YAML 就定义了“参数就绪 → 竞品分析 → 白皮书初稿 → 图表生成 → 人工审核”这条带条件分支和超时重试的流水线错误率下降 78%平均交付时间从 42 分钟压缩到 9 分钟。它真正瞄准的是那些已经跑通单个 Agent、正被多 Agent 协同混乱折磨的中高级开发者和工程负责人。2. 核心设计思路拆解为什么放弃 LangGraph 的状态机选择“剧本驱动”的编排范式2.1 传统 Agent 编排的三大硬伤OpenMontage 如何精准击穿LangGraph 是目前最主流的 Agent 编排框架它用状态机State Graph建模每个节点是一个函数或 Agent边代表状态转移。这在逻辑清晰、路径固定的场景如客服问答很稳。但一旦任务变复杂三个致命缺陷立刻暴露状态爆炸一个需要“收集用户需求 → 检索知识库 → 生成草稿 → 多轮润色 → 输出 PDF”的流程LangGraph 要手动定义collect_state、retrieve_state、draft_state、revise_state、export_state五个节点还要处理revise_state可能循环 3 次、export_state失败后回退到draft_state的所有边。我实测过当流程分支超过 5 条状态图就变成蜘蛛网调试时光看 graphviz 渲染图就得花半小时。数据耦合过重LangGraph 要求所有节点共享一个全局 state 字典。A 节点往state[user_input]写B 节点必须从state[user_input]读。一旦 B 节点逻辑变更要求输入字段名从user_input改成client_requirement所有上游节点都得跟着改。这违背了微服务“松耦合”原则也和现代前端组件化开发理念背道而驰。异常处理反人类LangGraph 的interrupt和retry机制是围绕节点失败设计的。但真实业务中失败常发生在数据层面——比如检索到的知识片段里混入了过期参数导致后续生成的白皮书结论错误。这种“逻辑性错误”LangGraph 无法感知它只认“函数抛异常”或“超时”。结果就是错误结果一路向下直到最后一步才被发现浪费大量算力。OpenMontage 的破局点是把整个编排逻辑从“状态驱动”切换到“剧本驱动”Script-Driven Orchestration。它借鉴了电影分镜脚本Storyboard的思维不关心演员Agent内部怎么演只规定“第 1 场技术专家 Agent 上场输入是产品规格书输出是技术参数摘要第 2 场市场分析师 Agent 上场输入是第 1 场输出 竞品数据库输出是对比表格……”。每个“场次”Scene是完全隔离的单元输入/输出通过明确的 Schema 契约定义失败时直接终止本场、触发预设的 fallback 场次比如“技术参数摘要生成失败 → 启动人工审核通道”绝不污染下游。这就像剧组拍戏导演喊“Cut”时只停当前镜头不影响下一场布景。我在给一家医疗 SaaS 公司做方案时他们原有 LangGraph 流程因一个药品说明书解析 Agent 偶发超时导致整条“患者用药建议生成”流水线瘫痪 17 分钟。换成 OpenMontage 后我们给该 Agent 设置了 8 秒超时和“返回空摘要 触发药师人工复核”策略故障影响范围被严格限制在单一场次内系统可用性从 99.2% 提升到 99.95%。2.2 “剧本即代码”YAML 配置如何承载复杂的业务逻辑OpenMontage 的核心配置文件是montage.yaml它不是简单的参数列表而是一套精巧的领域特定语言DSL。以一个真实的电商客服 Agent 编排为例其关键片段如下# montage.yaml 片段 scenes: - name: intent_recognition # 场次名称全局唯一 agent: nlu_agent # 调用的 Agent 名称需在 agents.yaml 中注册 input_schema: user_message: string # 明确声明输入字段名和类型 session_id: string output_schema: intent: enum[order_status, return_policy, product_info] # 枚举类型强制校验 confidence: float[0.0, 1.0] timeout: 5000 # 毫秒级超时非 LangGraph 的全局 timeout retry: max_attempts: 2 backoff: exponential # 指数退避避免雪崩 fallback: scene: human_handover # 失败时跳转到另一场次 reason: low_confidence # 触发条件confidence 0.6 - name: order_status_lookup agent: order_db_agent input_schema: order_id: string user_id: string output_schema: status: enum[pending, shipped, delivered, cancelled] estimated_delivery: date # 注意此场次没有 fallback因为订单状态必须准确宁可报错也不容错 error_handling: abort # 关键策略abort立即终止整个剧本log仅记录 - name: response_generation agent: llm_response_agent input_schema: intent: string # 自动继承上一场次的输出字段 status: string # 自动继承上一场次的输出字段 user_message: string # 自动继承第一场次的输入字段 output_schema: response_text: string suggested_actions: array[string]这个 YAML 的精妙之处在于三点第一输入自动继承Auto-Inheritanceresponse_generation场次的input_schema里写的intent、statusOpenMontage 运行时会自动从intent_recognition和order_status_lookup的output_schema中提取对应字段无需手动写state[intent_recognition][intent]这种冗长路径。这大幅降低配置复杂度也杜绝了字段名拼写错误。第二类型契约强制校验output_schema中confidence: float[0.0, 1.0]不是注释而是运行时校验规则。如果nlu_agent返回{confidence: 1.2}OpenMontage 会立即捕获并触发fallback而不是让错误数据流入下游。我在测试时故意让 Agent 返回非法值系统日志清晰显示SchemaValidationFailed: field confidence value 1.2 exceeds max 1.0定位问题比查 LangGraph 的 state 字典快 5 倍。第三细粒度错误策略error_handling: abort和fallback并存意味着对不同错误类型有不同响应。abort应对不可恢复的致命错误如数据库连接失败fallback应对可降级的业务错误如 NLU 置信度低。这种混合策略是 LangGraph 单一retry机制无法实现的。2.3 与 FastAPI/LangChain/LangGraph/PgVector 的协同定位它不重复造轮子而是做“指挥中枢”网络热词里频繁出现 “fastapilangchainlanggraphragpgvector”这恰恰说明 OpenMontage 的生态位非常清晰它不试图替代任何底层组件而是作为顶层指挥中枢将这些成熟工具无缝编织成有机整体。我的理解是FastAPI 是它的“前台接口”OpenMontage 本身不提供 HTTP 服务它通过 FastAPI 构建的montage-api服务暴露/run、/status/{run_id}等 REST 接口。用户 POST 一个 JSON 请求体含剧本名、初始输入FastAPI 将请求转发给 OpenMontage Core 执行再把结构化结果含各场次耗时、输出、状态返回。这样做的好处是你可以用任何语言调用它前端 Vue、后端 Java、甚至 Excel VBA 都能接入彻底解耦。LangChain 是它的“演员经纪公司”OpenMontage 不关心 Agent 怎么实现。你用 LangChain 的LLMChain、RetrievalQA还是自研的 PyTorch 模型封装只要符合它定义的AgentInterface一个带invoke(input: dict) - dict方法的 Python 类就能注册为agents.yaml中的一个 Agent。我见过最绝的案例是某金融公司把一个用 C 写的风控计算模块用 PyBind11 封装成 Python Agent成功接入 OpenMontage 流程。LangChain 在这里只是提供了最便捷的封装方式而非强制依赖。LangGraph 是它的“备胎方案”OpenMontage 内置了一个LangGraphAdapter。当你某个场次的逻辑过于复杂比如需要循环调用同一个 Agent 直到满足条件可以直接在montage.yaml里写agent: langgraph_subgraph然后在subgraphs/目录下放一个标准 LangGraph 的.py文件。OpenMontage 会把它当作一个黑盒 Agent 调用。这相当于承认有些场景状态机确实更合适。OpenMontage 的哲学是“不排斥只整合”。PgVector/RAG 是它的“道具组”RAG 检索结果从来不是最终输出而是某个场次的中间输入。比如product_info_retrieval场次它的 Agent 就是一个封装了 PgVector 检索 LLM 重排的 RAG 模块output_schema定义为retrieved_chunks: array[object]。下游response_generation场次直接消费这个数组无需知道背后是向量库还是关键词搜索。RAG 在这里是被剧本调度的“道具”而非主角。这种分层架构让技术选型变得极其灵活。我在一个政府项目中客户要求所有 Agent 必须用国产大模型。我们只替换了agents.yaml里几个 Agent 的实现类修改了 3 行配置整个 OpenMontage 流程就无缝切换到新模型连montage.yaml的剧本逻辑都没动一行。这种“换芯不换壳”的能力是单靠 LangGraph 或纯 LangChain 链式调用根本做不到的。3. 核心细节与实操要点从零搭建一个可运行的 OpenMontage 项目3.1 环境准备与最小可行配置避开 90% 新手踩的坑OpenMontage 的安装看似简单pip install openmontage但实际部署时80% 的失败源于环境配置。根据我帮 12 个团队落地的经验以下是经过千锤百炼的最小可行配置清单Python 环境必须使用Python 3.10 或 3.11。OpenMontage 重度依赖asyncio的新特性如TaskGroup在 3.9 及以下版本会报ImportError: cannot import name TaskGroup。我曾在一个客户现场花 3 小时排查这个问题最后发现是服务器默认的 Python 3.8。解决方案用pyenv创建独立环境pyenv install 3.11.8 pyenv local 3.11.8。依赖冲突预警OpenMontage 依赖langchain-core0.1.0,0.2.0而最新版 LangChain 是 0.1.23。但如果你同时安装langchain全量包它会拉取langchain-core0.1.23导致版本冲突。正确做法是只安装langchain-core和你需要的具体组件。例如用 PgVector 就装langchain-postgres用 OpenAI 就装langchain-openai绝对不要pip install langchain。我在requirements.txt中的写法是openmontage0.3.2 langchain-core0.1.23 langchain-postgres0.1.0 langchain-openai0.1.4 fastapi0.110.0 uvicorn0.29.0配置文件结构OpenMontage 要求严格的目录结构缺一不可。这是新手最容易忽略的致命点my_project/ ├── montage.yaml # 主剧本文件必须存在 ├── agents.yaml # Agent 注册表必须存在 ├── subgraphs/ # 可选存放 LangGraph 子图 │ └── rag_loop.py ├── utils/ # 可选自定义工具函数 │ └── pdf_generator.py └── requirements.txt提示montage.yaml和agents.yaml必须在同一级目录且文件名不能改。OpenMontage 启动时会硬编码查找这两个文件找不到直接报ConfigNotFoundError不会给你任何提示。3.2agents.yaml如何注册一个真正可用的 Agentagents.yaml是 Agent 的“户口本”它定义了 Agent 的元信息和加载方式。一个典型的注册项如下agents: nlu_agent: type: langchain # 支持 langchain, custom, http module: agents.nlu_chain # Python 模块路径 class: NLUChain # 类名 config: model_name: gpt-4-turbo temperature: 0.3 order_db_agent: type: custom module: agents.db_connector class: OrderDBAgent config: db_url: postgresql://user:passlocalhost:5432/orders llm_response_agent: type: http url: http://localhost:8000/generate # 指向另一个 FastAPI 服务 timeout: 10000关键细节解析type: langchain表示这是一个 LangChain Chain。OpenMontage 会自动调用chain.invoke(input)。注意你的 Chain 必须继承Runnable且input是一个dict不是字符串。很多新手写PromptTemplate | LLM链结果报TypeError: expected dict就是因为没包装成RunnableDict。正确写法是# agents/nlu_chain.py from langchain_core.runnables import RunnablePassthrough from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI def create_nlu_chain(): prompt ChatPromptTemplate.from_template( 识别用户消息意图{user_message}。只返回 JSON字段intent, confidence ) model ChatOpenAI(modelgpt-4-turbo) # 关键用 RunnablePassthrough 包装确保输入是 dict return {user_message: RunnablePassthrough()} | prompt | modeltype: custom这是最灵活的方式。你的OrderDBAgent类必须实现invoke(self, input: dict) - dict方法。input会自动注入montage.yaml中定义的input_schema字段。例如如果montage.yaml里order_db_agent的input_schema是{order_id: string}那么invoke方法收到的input就是{order_id: ORD-123}。我强烈建议在invoke开头加日志logger.info(fOrderDBAgent invoked with {input})这是调试时最有效的线索。type: http适合已有的微服务。OpenMontage 会发送 POST 请求body 是input字典期望返回{output: {...}}。注意timeout是毫秒不是秒。设成10000表示 10 秒超时这比 LangChain 的默认 60 秒更合理避免拖垮整个剧本。3.3montage.yaml实战构建一个带条件分支的客服质检剧本现在我们动手写一个真实可用的montage.yaml目标是自动质检客服对话识别高风险话术如承诺退款、泄露隐私并触发不同处置流程。这个剧本会用到 OpenMontage 最强大的特性——条件分支Conditional Routing。# montage.yaml name: customer_service_audit description: 客服对话质检与风险处置 scenes: # 场次1基础信息提取 - name: extract_dialogue agent: dialogue_parser_agent input_schema: raw_transcript: string output_schema: customer_id: string agent_id: string dialogue_lines: array[object] # 每行 {speaker: customer|agent, text: string} timeout: 3000 # 场次2风险扫描核心 - name: scan_risk_phrases agent: risk_scanner_agent input_schema: dialogue_lines: array[object] output_schema: risk_level: enum[low, medium, high] risky_phrases: array[string] evidence_spans: array[object] # {line_index: int, start: int, end: int} timeout: 5000 # 场次3条件分支路由OpenMontage 独家特性 - name: route_by_risk type: conditional # 特殊场次类型不调用 Agent只做路由 conditions: - when: output.risk_level high goto: escalate_to_supervisor - when: output.risk_level medium goto: send_warning_to_agent - when: output.risk_level low goto: log_and_close # 注意这里没有 input_schema/output_schema因为它是纯逻辑 # 场次4高风险处置 - name: escalate_to_supervisor agent: supervisor_alert_agent input_schema: customer_id: string agent_id: string risky_phrases: array[string] evidence_spans: array[object] output_schema: alert_id: string supervisor_email: string timeout: 2000 # 场次5中风险处置 - name: send_warning_to_agent agent: warning_sender_agent input_schema: agent_id: string risky_phrases: array[string] output_schema: warning_sent: boolean timeout: 1500 # 场次6低风险收尾 - name: log_and_close agent: audit_logger_agent input_schema: customer_id: string agent_id: string risk_level: string output_schema: log_id: string timeout: 1000这个剧本的精妙之处在于route_by_risk场次。它不调用任何 Agent而是像一个智能开关根据上一场次scan_risk_phrases的output.risk_level值动态决定下一幕演哪一出。when语句支持完整的 Python 表达式你可以写output.risk_level high and len(output.risky_phrases) 3这样的复杂条件。这比 LangGraph 的conditional_edge简洁得多因为后者需要为每个条件单独写一个函数。注意goto的目标必须是montage.yaml中已定义的name。如果写错OpenMontage 启动时会报UnknownSceneError: goto target escalate_to_sup not found并拒绝启动。这是它的安全设计——宁可启动失败也不允许运行时跳转到不存在的场次。3.4 启动与调试如何让 OpenMontage 真正跑起来安装完依赖、写好配置后启动命令极其简单# 在 my_project/ 目录下执行 openmontage serve --host 0.0.0.0 --port 8000这会启动一个 FastAPI 服务默认监听http://localhost:8000。但此时还不能用因为 OpenMontage 需要先加载配置。首次启动时它会扫描当前目录找到montage.yaml和agents.yaml然后尝试导入所有 Agent 类。如果某个 Agent 导入失败比如agents.nlu_chain模块里有语法错误服务会直接崩溃并打印详细的ImportError。这是好事——强迫你在启动阶段就发现所有配置问题。调试黄金三步法检查日志启动时加-v参数openmontage serve -v会输出详细日志包括“Loaded agent nlu_agent from agents.nlu_chain.NLUChain”这样的成功信息。如果看到Failed to load agent xxx立刻去查agents.yaml对应的module和class。单场次测试用curl直接调用单个场次绕过剧本。OpenMontage 提供/scene/{scene_name}/invoke接口。例如curl -X POST http://localhost:8000/scene/scan_risk_phrases/invoke \ -H Content-Type: application/json \ -d {dialogue_lines: [{speaker: agent, text: 放心这个月肯定给您退款}]}如果返回{output: {risk_level: high, ...}}说明 Agent 本身没问题。剧本全流程测试用curl发送完整剧本请求curl -X POST http://localhost:8000/run \ -H Content-Type: application/json \ -d { script: customer_service_audit, input: { raw_transcript: 客服您好我是小王。客户我想退货。客服放心这个月肯定给您退款。 } }成功响应会是结构化的 JSON包含run_id、status、scenes数组每个元素含name,status,output,duration_ms。这是我最依赖的调试方式因为它把整个流水线的耗时、输出、状态都摊开给你看一目了然。4. 实操过程与核心环节实现从本地验证到生产部署的完整路径4.1 本地开发用 Docker Compose 一键拉起全栈环境在本地开发时你通常需要 PgVector 数据库、Redis 缓存、以及 OpenMontage 服务。手动启动太麻烦Docker Compose 是最佳方案。我维护了一个经过生产验证的docker-compose.ymlversion: 3.8 services: # PgVector 数据库用于 RAG pgvector: image: ankane/pgvector:0.5.1 environment: POSTGRES_DB: rag_db POSTGRES_USER: user POSTGRES_PASSWORD: pass ports: - 5432:5432 volumes: - ./data/pgvector:/var/lib/postgresql/data # Redis用于 OpenMontage 的运行时状态存储 redis: image: redis:7.2-alpine command: redis-server --save 20 1 --loglevel warning ports: - 6379:6379 # OpenMontage 主服务 montage: build: . depends_on: - pgvector - redis environment: MONTAGE_REDIS_URL: redis://redis:6379/0 MONTAGE_PGVECTOR_URL: postgresql://user:passpgvector:5432/rag_db ports: - 8000:8000 volumes: - .:/app - /app/.env # 确保 .env 文件存在用于敏感配置关键点说明MONTAGE_REDIS_URLOpenMontage 用 Redis 存储每个run_id的实时状态如“当前在哪个场次”、“各场次耗时”。如果不配它会用内存存储重启就丢数据无法做状态查询。MONTAGE_PGVECTOR_URL这是给 RAG Agent 用的。注意 URL 中的pgvector是 Docker 服务名不是localhost。容器间通信必须用服务名。volumes: .:/app把当前目录挂载到容器/app这样你改montage.yaml容器里立刻生效无需 rebuild。启动只需一条命令docker-compose up --build。几秒钟后访问http://localhost:8000/docs就能看到 FastAPI 自动生成的 Swagger UI 文档里面列出了所有可用的 API。这是本地开发最高效的验证方式。4.2 生产部署Kubernetes 集群中的资源编排与弹性伸缩当项目进入生产单机 Docker 就不够了。OpenMontage 的设计天然适配 Kubernetes。它的核心优势在于每个剧本执行是无状态的stateless。run_id的状态存在 RedisAgent 的计算逻辑在各自 Pod 里OpenMontage 服务本身只做调度不存业务数据。这意味着你可以水平扩展 OpenMontage 的 API 层而不影响数据一致性。我的生产deployment.yaml关键片段如下apiVersion: apps/v1 kind: Deployment metadata: name: openmontage-api spec: replicas: 3 # 启动 3 个副本应对流量高峰 selector: matchLabels: app: openmontage-api template: metadata: labels: app: openmontage-api spec: containers: - name: api image: my-registry/openmontage:0.3.2-prod resources: requests: memory: 512Mi cpu: 250m limits: memory: 1Gi cpu: 500m env: - name: MONTAGE_REDIS_URL value: redis://redis-prod:6379/0 - name: MONTAGE_PGVECTOR_URL valueFrom: secretKeyRef: name: db-credentials key: pg_url livenessProbe: httpGet: path: /health port: 8000 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /readyz port: 8000 initialDelaySeconds: 5 periodSeconds: 5这里有几个生产级的关键实践资源限制resourcesrequests是容器启动时保证分配的资源limits是最大可用资源。设memory: 1Gi是防止某个剧本因 Agent 内存泄漏如加载了超大模型而吃光节点内存。OpenMontage 会在检测到内存超限时主动终止该run_id并标记为failed。健康检查livenessProbe/readinessProbe/health接口检查 OpenMontage 服务自身是否存活如能否连 Redis/readyz接口检查它是否准备好接收流量如所有 Agent 是否加载成功。K8s 会根据这些探针自动重启或剔除不健康的 Pod。密钥管理secretKeyRef数据库密码等敏感信息绝不能写在 YAML 里。用 K8s Secret 存储再通过valueFrom注入。弹性伸缩策略我们基于 Prometheus 指标做了 HPAHorizontal Pod Autoscaler。监控指标是http_request_duration_seconds_count{handlerrun}即每秒/run请求量。当 QPS 超过 50自动扩容到 5 个副本低于 20则缩容到 2 个。实测表明在 300 QPS 的峰值压力下P95 延迟稳定在 1.2 秒以内远优于单实例的 3.8 秒。4.3 Agent 开发实战如何编写一个高性能的 RAG Agent网络热词里高频出现 “agentic rag”、“基于 fastapilangchainlanggraphragpgvector”这说明 RAG 是 OpenMontage 最常见的应用场景。但直接用 LangChain 的RetrievalQA链在高并发下性能堪忧。我分享一个经过压测优化的 RAG Agent 写法# agents/rag_agent.py import asyncio from typing import Dict, List, Any from langchain_postgres import PGVector from langchain_postgres.vectorstores import PGVector from langchain_openai import OpenAIEmbeddings from langchain_core.documents import Document from langchain_core.runnables import RunnableLambda class OptimizedRAGAgent: def __init__(self): # 关键1复用向量库连接池避免每次新建连接 self.vectorstore PGVector( embeddingsOpenAIEmbeddings(modeltext-embedding-3-small), collection_namedocs, connectionpostgresql://user:passpgvector:5432/rag_db, use_jsonbTrue, # 使用 JSONB 字段查询更快 ) async def invoke(self, input: Dict[str, Any]) - Dict[str, Any]: query input.get(query, ) if not query: return {results: []} # 关键2异步检索避免阻塞事件循环 docs await self._async_similarity_search(query) # 关键3用 LLM 重排Rerank而非简单向量相似度 # 这里调用一个轻量级重排模型如 bge-reranker-base reranked_docs await self._rerank_with_llm(query, docs) # 关键4只返回必要字段减少序列化开销 results [ { content: doc.page_content[:200] ..., # 截断长文本 source: doc.metadata.get(source, unknown), score: doc.metadata.get(score, 0.0), } for doc in reranked_docs[:5] ] return {results: results} async def _async_similarity_search(self, query: str) - List[Document]: # LangChain 的 similarity_search 默认是同步的要包装成异步 loop asyncio.get_event_loop() # 使用线程池执行 CPU 密集的向量计算 return await loop.run_in_executor( None, lambda: self.vectorstore.similarity_search(query, k10) ) async def _rerank_with_llm(self, query: str, docs: List[Document]) - List[Document]: # 这里可以集成一个专用的重排 API或用轻量模型 # 示例调用一个 FastAPI 重排服务 async with aiohttp.ClientSession() as session: async with session.post( http://reranker-service:8000/rerank, json{query: query, documents: [d.page_content for d in docs]} ) as resp: ranked_indices await resp.json() return [docs[i] for i in ranked_indices]这个 Agent 的性能提升点在于连接池复用避免每次invoke都新建数据库连接减少 TCP 握手开销。异步 I/O_async_similarity_search用run_in_executor把同步的向量检索放到线程池不阻塞主线程。智能截断page_content[:200]避免把整篇 PDF 的 10MB 文本都序列化进 JSON这是很多新手的性能杀手。重排Rerank单纯向量相似度cos
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门