Vidura开源框架:模块化AI对话编排与自动化评估实战指南
1. 项目概述一个开源的AI对话编排与评估框架最近在折腾AI应用开发特别是涉及到多模型对话、复杂工作流编排和效果评估时总感觉市面上现成的工具要么太重要么太零散。直到我发现了Vidura这个项目它像是一套为AI对话系统量身定制的“乐高积木”和“质检工具”的结合体。简单来说Vidura是一个开源框架它允许开发者以一种结构化的方式去设计、编排、执行和评估复杂的AI对话流程。想象一下这样的场景你需要构建一个客服机器人它不仅要能理解用户意图可能还需要根据对话内容去查询数据库、调用外部API获取实时信息最后再调用合适的AI模型比如GPT-4、Claude或者本地部署的Llama生成回复并且你还需要一套机制来评估这个回复的质量。如果每个环节都自己从头搭建光是处理不同模型API的差异、管理对话状态、设计评估指标就够头疼了。Vidura的价值就在于它把这些繁琐但通用的部分抽象出来提供了统一的接口和模块化的组件让你能更专注于业务逻辑本身。这个项目适合谁呢我认为主要面向几类人一是正在构建复杂AI对话应用的开发者或团队尤其是那些需要混合调用多个AI模型、集成外部工具的场景二是需要对AI对话效果进行系统性评估和迭代的研究人员或产品经理三是任何对AI Agent、工作流自动化感兴趣想学习现代AI应用架构的爱好者。即使你只是用一个模型做简单的对话Vidura里关于评估和数据集管理的部分也极具参考价值。2. 核心架构与设计理念拆解2.1 模块化与可插拔的设计哲学Vidura的核心设计思想非常清晰解耦与组合。它没有试图做一个大而全的、封闭的对话系统而是将整个对话生命周期拆解成一系列独立的、功能单一的模块。这种设计带来的最大好处就是灵活性。你可以像搭积木一样根据你的需求选择不同的模块进行组合。整个框架大致可以划分为几个核心层编排层Orchestration Layer这是大脑负责定义对话的流程。比如是先进行意图识别还是先查询知识库判断条件是什么Vidura允许你使用YAML或Python来定义这些工作流工作流由一个个节点Node组成节点之间通过边Edge连接清晰地描述了执行路径和逻辑分支。组件层Component Layer这是执行具体任务的“工人”。每个节点在运行时实际上是在调用一个或多个组件。组件是具体功能的实现例如模型组件封装了对OpenAI、Anthropic、Cohere等云端模型API的调用或者对本地Ollama、vLLM等推理引擎的调用。统一了输入输出格式。工具组件用于执行具体操作比如计算器、网络搜索、数据库查询、调用企业内部API等。这赋予了AI“动手能力”。记忆组件管理对话历史决定哪些历史消息需要被保留并送入模型的上下文窗口这是实现多轮连贯对话的关键。评估组件用于对模型输出或整个对话流程进行打分、分类或分析。评估与数据集层Evaluation Dataset Layer这是Vidura非常出彩的部分。它内置了一套评估系统允许你定义评估标准例如相关性、安全性、事实准确性并使用AI模型甚至是另一个模型或规则来自动化评估。同时它提供了数据集管理功能你可以方便地导入、创建用于测试和评估的对话数据集。这种模块化设计意味着当你需要更换一个AI模型提供商时可能只需要修改配置文件中模型组件的API密钥和端点而无需触动任何业务流程代码。当需要增加一个新功能如情感分析时你只需要开发一个新的组件并将其插入到工作流的合适节点即可。2.2 基于有向无环图DAG的工作流引擎Vidura底层的工作流引擎通常基于有向无环图DAG的概念。这是现代任务编排系统如Apache Airflow的常见模式将其应用于AI对话编排非常贴切。在一个对话DAG中节点Node代表一个原子操作例如“调用GPT-4生成回复”、“使用工具查询天气”、“根据关键词检索知识库”。边Edge代表节点之间的依赖关系和执行顺序。边可以带有条件例如“如果用户情绪为负面则跳转到安抚流程节点”。这种图示化的思维方式让复杂的对话逻辑变得直观且易于维护。你可以清晰地看到用户输入后数据是如何在各个处理单元间流动的最终又是如何汇聚成回复的。对于调试和优化流程来说这比跟踪一堆嵌套的if-else语句要高效得多。实操心得在初期设计工作流时不要急于写YAML或代码。先用纸笔画出一个简单的DAG草图明确每个节点的输入、输出以及分支条件。这能帮你理清思路避免设计出循环依赖或逻辑死角。Vidura的这类设计强迫开发者进行结构化思考这本身就是一个很好的实践。3. 核心组件深度解析与配置要点3.1 模型组件的统一与抽象模型组件是Vidura与AI模型交互的桥梁。它的核心价值在于统一了异构模型的调用接口。不同的模型API在参数命名、请求格式、响应结构上各有不同。Vidura的模型组件抽象层帮你处理了这些差异。一个典型的模型组件配置可能长这样以YAML为例components: - name: gpt-4-turbo-chat type: model provider: openai config: model: gpt-4-turbo api_key: ${env.OPENAI_API_KEY} temperature: 0.7 max_tokens: 1024 system_prompt: “你是一个专业的客服助手回答要简洁、准确、友好。”这里的关键点provider指定了后端服务商如openai、anthropic、cohere、ollama本地等。Vidura需要为每个provider实现对应的适配器。config这里的参数会映射到对应API的实际参数。temperature、max_tokens这些是通用概念适配器会负责将其翻译成目标API的特定字段。system_prompt这是一个非常重要的配置。它定义了模型的“角色”和基础行为准则。好的system prompt能极大提升对话的稳定性和质量。建议将其作为可配置的变量针对不同场景的工作流使用不同的prompt。注意事项对于api_key等敏感信息务必像示例中一样通过环境变量${env.XXX}引用绝对不要硬编码在配置文件中。你可以创建一个.env文件来管理所有密钥并在启动应用时加载。3.2 工具组件的扩展与实践工具组件让AI从“聊天脑”变成了“执行手”。Vidura的工具组件遵循一个通用的模式定义工具的功能描述供AI模型理解并实现具体的执行函数。例如创建一个获取股价的工具# 伪代码示例说明概念 from vidura.sdk import ToolComponent class GetStockPriceTool(ToolComponent): name “get_stock_price” description “获取指定股票代码的当前价格。输入应为股票代码如‘AAPL’。” def execute(self, input_data: str) - str: # input_data 会是 “AAPL” stock_code input_data # 这里调用真实的金融数据API price call_finance_api(stock_code) return f”股票 {stock_code} 的当前价格是 {price} 美元。”在工作流中你可以设计一个节点先让模型判断用户是否在询问股价如果是则提取股票代码然后调用这个GetStockPriceTool组件最后将工具返回的结果再交给模型让其组织成一句人话回复给用户。工具设计的关键描述要清晰准确description字段会被送入模型的上下文帮助模型理解何时该调用此工具。描述应明确说明输入格式和工具功能。输入输出要稳定工具的执行函数应能处理各种边界情况如无效输入并返回结构化的结果。返回纯文本通常是最兼容的方式。安全性工具能访问外部系统或网络必须加入权限控制和输入验证防止被恶意利用。3.3 记忆组件的策略与实现记忆管理是对话系统的核心难题。Vidura的记忆组件通常提供多种策略完整历史保存所有对话轮次。简单但消耗上下文窗口快。滑动窗口只保留最近N轮对话。平衡了记忆和效率。摘要记忆定期或按需将过往对话总结成一段摘要然后将摘要和近期对话一起送入上下文。这是处理长对话的先进策略。向量记忆将对话片段转换成向量存入向量数据库根据当前查询进行语义检索找回相关记忆。这适合知识密集型对话。在Vidura中配置记忆组件你需要关注几个参数memory_type: 选择上述策略之一。window_size: 如果是滑动窗口指定窗口大小。summary_model: 如果使用摘要记忆指定用于生成摘要的模型可以是一个更小、更快的模型。实操心得对于大多数客服或问答场景“滑动窗口关键信息提取”是一个不错的起点。例如在对话中自动提取用户姓名、订单号等实体信息并将其作为独立于对话窗口的“长期记忆”存储在后续对话中显式注入。这比单纯依赖模型的上下文记忆更可靠。4. 从零构建一个客服工作流实操全流程让我们通过一个具体的例子看看如何用Vidura构建一个简单的智能客服工作流处理“查询订单状态”和“产品咨询”两类问题。4.1 环境准备与项目初始化首先确保你的Python环境建议3.9以上并安装Vidura。通常可以通过pip安装其核心包或者从GitHub克隆仓库进行本地开发。# 假设vidura已发布到PyPI pip install vidura-core # 或者从源码安装 git clone https://github.com/narenaryan/Vidura.git cd Vidura pip install -e .接下来创建你的项目目录结构。一个清晰的结构有助于管理my_customer_service/ ├── configs/ │ ├── workflow.yaml # 主工作流定义 │ └── models.yaml # 模型配置 ├── components/ │ ├── custom_tools.py # 自定义工具组件 │ └── __init__.py ├── data/ # 存放测试数据集 ├── .env # 环境变量API密钥等 └── main.py # 应用入口在.env文件中设置你的API密钥OPENAI_API_KEYsk-your-key-here ANTHROPIC_API_KEYyour-claude-key-here4.2 定义工作流与组件配置在configs/workflow.yaml中定义我们的客服DAGname: customer_service_workflow description: 一个处理订单查询和产品咨询的客服工作流。 components: # 定义模型组件 - name: classifier_model type: model provider: openai config: model: gpt-3.5-turbo # 用便宜快速的模型做分类 temperature: 0.1 # 低随机性保证分类稳定 system_prompt: “你是一个意图分类器。请将用户问题分类为‘order_status’查询订单状态、‘product_inquiry’产品咨询或‘other’其他。只输出类别名称。” - name: main_chat_model type: model provider: openai config: model: gpt-4-turbo temperature: 0.7 system_prompt: “你是一家科技公司的专业客服代表态度热情、乐于助人。请根据提供的信息回答用户问题。” # 定义工具组件假设我们已经实现 - name: order_lookup_tool type: tool class_path: “components.custom_tools.OrderLookupTool” # 指向自定义类 - name: product_db_tool type: tool class_path: “components.custom_tools.ProductDatabaseTool” workflow: start_node: classify_intent nodes: - id: classify_intent type: component component: classifier_model inputs: user_input: “{{ user_message }}” outputs: intent: “{{ model_response }}” - id: handle_order_status type: component component: order_lookup_tool inputs: order_id: “{{ extracted_order_id }}” # 假设前面有节点提取了ID outputs: order_info: “{{ tool_result }}” conditions: - when: “{{ parent.classify_intent.outputs.intent }} ‘order_status’” then: proceed - id: handle_product_inquiry type: component component: product_db_tool inputs: product_name: “{{ extracted_product_name }}” outputs: product_details: “{{ tool_result }}” conditions: - when: “{{ parent.classify_intent.outputs.intent }} ‘product_inquiry’” then: proceed - id: generate_final_response type: component component: main_chat_model inputs: # 动态构造输入根据意图组合不同的上下文信息 context: | 用户问题{{ user_message }} {% if intent ‘order_status’ %} 订单信息{{ order_info }} {% elif intent ‘product_inquiry’ %} 产品信息{{ product_details }} {% endif %} 请生成回复。 outputs: final_response: “{{ model_response }}”这个YAML定义了一个清晰的工作流classify_intent节点先用小模型对用户问题进行分类。根据分类结果条件性地执行handle_order_status或handle_product_inquiry节点调用相应的工具获取真实数据。最后generate_final_response节点汇集原始问题、意图和工具查询结果交给主模型GPT-4生成友好、准确的最终回复。4.3 实现自定义工具组件现在我们需要在components/custom_tools.py中实现用到的工具。这里以OrderLookupTool为例import logging from typing import Any, Dict from vidura.sdk import ToolComponent # 模拟一个订单数据库 MOCK_ORDER_DB { “ORD123456”: {“status”: “已发货”, “estimated_delivery”: “2023-10-27”, “items”: [“手机X1”]}, “ORD654321”: {“status”: “处理中”, “estimated_delivery”: “2023-11-05”, “items”: [“耳机Y1”]}, } class OrderLookupTool(ToolComponent): name “order_lookup” description “根据订单号查询订单状态和预计送达时间。输入应为订单号字符串。” def execute(self, input_data: str, **kwargs) - Dict[str, Any]: order_id input_data.strip().upper() logging.info(f”正在查询订单: {order_id}“) if order_id in MOCK_ORDER_DB: order_info MOCK_ORDER_DB[order_id] return { “success”: True, “order_id”: order_id, “status”: order_info[“status”], “estimated_delivery”: order_info[“estimated_delivery”], “items”: order_info[“items”] } else: return {“success”: False, “error”: “未找到该订单号”, “order_id”: order_id} # 可选定义一个后处理函数将返回的字典格式化成给模型看的文本 def format_for_model(self, result: Dict[str, Any]) - str: if result[“success”]: items “, “.join(result[“items”]) return f”订单 {result[‘order_id’]} 状态为‘{result[‘status’]}’预计送达时间 {result[‘estimated_delivery’]}。包含商品{items}。” else: return f”抱歉未找到订单 {result[‘order_id’]}请核对订单号是否正确。”在实际生产中execute方法内部会替换为对真实订单数据库或API的调用。format_for_model方法是一个好实践它确保了工具返回的信息以一种易于模型理解和利用的格式呈现。4.4 运行与测试工作流最后在main.py中编写加载和运行工作流的代码import asyncio import os from dotenv import load_dotenv from vidura import ViduraEngine # 加载环境变量 load_dotenv() async def main(): # 初始化引擎指定配置文件路径 engine ViduraEngine(config_path“./configs/workflow.yaml”) # 测试对话 test_messages [ “我的订单ORD123456到哪里了”, “你们新出的旗舰手机有什么颜色”, “今天天气怎么样” ] for msg in test_messages: print(f”\n 用户输入: {msg} ) # 执行工作流传入初始用户输入 result await engine.execute(initial_input{“user_message”: msg}) # 获取最终响应 final_response result.get(“final_response”, “未生成回复”) print(f”客服回复: {final_response}“) # 你也可以查看中间结果用于调试 # print(f”完整结果: {result}“) if __name__ “__main__”: asyncio.run(main())运行这个脚本你会看到工作流如何根据不同的用户输入走不同的分支路径并生成相应的回复。对于“今天天气怎么样”这种“other”类问题由于我们没有设计处理分支最终回复可能会由main_chat_model根据其系统提示直接生成一个通用回应如“我主要处理订单和产品咨询暂时无法查询天气”。5. 评估系统如何衡量与优化你的对话AI构建了工作流只是第一步如何知道它表现得好不好Vidura的评估系统提供了答案。评估不是一次性的而应是一个持续的迭代循环构建 - 评估 - 分析 - 改进。5.1 定义评估指标与评估器评估始于定义清晰的指标。Vidura通常支持多种评估器EvaluatorAI即评估器使用一个AI模型如GPT-4来评估另一个AI的输出。例如给出问题、参考答案和实际回答让GPT-4从“相关性”、“有帮助性”、“准确性”等维度打分1-5分。这种方法灵活但成本较高且可能不稳定。规则评估器基于正则表达式、关键词匹配或逻辑判断。例如检查回复中是否包含“订单号”等敏感信息不应出现或者回复长度是否在合理范围内。自定义评估器你可以编写任何Python函数作为评估器例如调用一个外部的情感分析API来判断回复语气是否友好。在配置中定义评估指标可能如下所示evaluation: metrics: - name: relevance evaluator: llm_as_judge config: judge_model: gpt-4-turbo criteria: “评估回复是否与用户问题直接相关。完全相关得5分完全不相关得1分。” scoring_range: [1, 5] - name: contains_pii evaluator: regex config: patterns: [“\d{18}“, “\d{4}-\d{4}-\d{4}-\d{4}“] # 匹配身份证、信用卡号等 action: “penalize” # 如果匹配到则扣分 - name: response_length evaluator: custom class_path: “my_evaluators.LengthEvaluator” config: min_words: 5 max_words: 2005.2 创建与管理测试数据集没有数据评估就是无源之水。Vidura鼓励你建立结构化的测试数据集。数据集通常是一个JSON或CSV文件每一行代表一个测试用例。// test_dataset.json [ { “id”: “test_case_1”, “user_input”: “订单ORD123456的状态是什么”, “expected_intent”: “order_status”, “expected_entities”: {“order_id”: “ORD123456”}, “expected_response_contains”: [“已发货”, “预计送达”] // 期望回复包含的关键词 }, { “id”: “test_case_2”, “user_input”: “手机电池能用多久”, “expected_intent”: “product_inquiry”, “expected_response_contains”: [“续航”, “小时”, “电池容量”], “forbidden_words”: [“不知道”, “无法回答”] // 回复中不应出现的词 } ]你可以使用Vidura的命令行工具或API将整个数据集灌入你的工作流进行批量测试并自动收集每个测试用例在所有评估指标上的得分。5.3 执行评估与结果分析运行评估后你会得到一份详细的报告。一份好的评估报告不仅仅是平均分更应该帮你定位问题。报告应包含总体得分各指标的平均分、中位数、分布情况。案例级详情每个测试用例的输入、实际输出、各指标得分。对于得分低的案例要能直接查看。错误归类自动或手动将失败案例归类如“意图识别错误”、“工具调用失败”、“回复不相关”、“包含禁语”等。对比分析如果你调整了系统提示prompt或工作流可以对比新旧版本的评估结果量化改进效果。实操心得不要盲目追求所有指标都得高分。根据你的场景确定核心指标。对于一个客服机器人“准确性”和“安全性”不泄露信息、不说错话的权重应该远高于“创造性”。初期可以设置一个“红线指标”比如“contains_pii”必须为0分任何触发的案例都需要最高优先级修复。评估是一个持续的过程建议将评估脚本集成到你的CI/CD流程中每次代码更新都自动跑一遍核心测试集。6. 部署、监控与性能调优实战6.1 部署模式选择开发完成后你需要将Vidura应用部署出去。根据负载和场景有几种选择脚本/CLI模式最简单的方式就像我们上面的main.py。适合内部工具、一次性任务或评估批处理。使用nohup或systemd即可在服务器后台运行。Web API服务最常用的模式。Vidura通常提供将工作流暴露为HTTP端点的能力。你可以使用FastAPI、Flask等框架快速包装引擎。# 使用FastAPI的简单示例 from fastapi import FastAPI from vidura import ViduraEngine import asyncio app FastAPI() engine None app.on_event(“startup”) async def startup_event(): global engine engine ViduraEngine(config_path“./configs/workflow.yaml”) # 可以在这里进行预加载等操作 app.post(“/chat”) async def chat_endpoint(request: dict): user_message request.get(“message”, “”) session_id request.get(“session_id”, “default”) try: result await engine.execute( initial_input{“user_message”: user_message}, session_idsession_id # 用于关联对话记忆 ) return {“response”: result.get(“final_response”, “”), “status”: “success”} except Exception as e: return {“response”: “”, “status”: “error”, “detail”: str(e)}部署时使用Gunicorn配合Uvicorn for ASGI或Uvicorn直接作为生产服务器。务必使用反向代理如Nginx处理SSL、负载均衡和静态文件。集成到现有应用将Vidura引擎作为你现有Python应用的一个模块导入和调用灵活度最高。6.2 关键监控指标与日志上线后监控至关重要。你需要关注性能指标延迟每个工作流或关键节点的平均响应时间P50 P95 P99。使用Prometheus Grafana进行采集和可视化。吞吐量每秒能处理的请求数QPS。错误率API调用失败、模型调用超时、工具执行异常的比例。业务/质量指标意图分布各类用户意图的比例帮你了解用户主要需求。工具调用成功率外部API或数据库查询的成功率。评估分数趋势定期如每天用测试集跑一次评估观察分数是否下降及时发现模型退化或流程问题。日志实施结构化日志如JSON格式记录每个请求的session_id、user_input、intent、tool_calls、final_response以及latency。这不仅是调试的黄金数据也是后续优化训练数据的来源。确保日志中不记录任何真实的个人身份信息PII。6.3 性能调优与成本控制随着用量增长性能和成本会成为焦点。性能调优方向缓存对频繁且结果不变的查询进行缓存。例如产品信息、常见问答对。可以在工具组件内部实现也可以在Vidura工作流前加一层缓存中间件。异步与非阻塞确保你的自定义工具组件和模型调用是异步的使用async/await避免阻塞事件循环。Vidura的核心引擎通常基于异步框架构建。节点并行化检查你的工作流DAG如果某些节点间没有依赖关系可以配置它们并行执行减少整体延迟。模型降级并非所有任务都需要GPT-4。像意图分类、实体提取这类相对简单的任务完全可以使用GPT-3.5 Turbo甚至更小的开源模型在保证效果的同时大幅降低成本。成本控制策略用量监控与告警密切监控各AI模型的token消耗设置每日或每月预算告警。大多数云服务商都提供此功能。上下文长度管理这是成本大头。积极使用前面提到的摘要记忆或向量检索记忆尽可能减少送入模型的冗余历史token。定期清理对话记忆。设置超时与重试为模型API调用和工具调用设置合理的超时时间。对于可重试的错误如网络抖动实施带退避策略的重试机制避免因临时故障导致不必要的失败和用户体验下降。评估成本自动化评估虽然好但用GPT-4评估GPT-3.5的输出评估成本可能比执行成本还高。考虑使用更便宜的模型如Claude Haiku做初步评估或增加规则评估的比例。7. 常见问题排查与调试技巧实录在实际使用中你肯定会遇到各种问题。以下是一些典型问题及其排查思路来自我个人的踩坑经验。7.1 工作流执行失败或卡住症状请求无响应或日志显示在某个节点后停止。排查步骤检查节点依赖与条件确认DAG中没有形成循环依赖。检查每个条件conditions语句的逻辑是否正确确保至少有一条路径可以到达终点。一个常见的错误是条件设置过于严格导致所有路径都被阻断。检查组件配置确认YAML中component字段引用的名称在components部分有正确定义且class_path指向的Python类可以被正确导入。查看详细日志启用Vidura的调试级别日志查看每个节点开始、结束以及传递的数据。问题往往出在数据的格式上比如某个节点输出的变量名与下游节点期望的输入变量名不匹配。隔离测试单独创建一个只包含可疑节点的小型工作流进行测试验证其输入输出是否符合预期。7.2 模型调用返回意外内容或错误症状回复质量差、胡言乱语或直接返回API错误。排查步骤验证API密钥与网络这是最常见的问题。确保环境变量已正确加载并且服务器可以访问对应的API端点考虑网络代理或防火墙规则。审查System Prompt和用户输入将实际发送给模型的请求内容打印出来注意脱敏。检查system prompt是否清晰定义了角色用户输入是否被意外截断或污染一个混乱的system prompt会导致模型行为异常。检查参数temperature设置是否过高导致随机性太大max_tokens是否足够生成完整回复对于需要严格格式的输出如分类、JSON尝试将temperature设为0或接近0并使用response_format参数如果API支持。处理速率限制如果请求量突然增大可能会触发API的速率限制。实现一个带有指数退避的请求重试逻辑并在日志中明确记录此类错误。7.3 工具组件执行异常症状工具调用失败返回错误或超时。排查步骤输入验证在工具的execute方法开头严格验证输入数据的类型和范围。模型生成的输入可能不符合预期。异常捕获与友好返回用try...except包裹核心逻辑捕获所有可能的异常网络超时、数据库连接失败、第三方API错误等并返回一个结构化的错误信息而不是让异常直接抛出导致整个工作流崩溃。这能让上游节点或模型有机会进行补救例如回复用户“系统暂时繁忙”。超时设置为所有外部调用设置显式的超时。一个慢速的外部API会拖垮整个对话的响应时间。模拟与测试为工具编写单元测试模拟各种正常和异常的输入确保其健壮性。7.4 评估分数不稳定或偏低症状自动化评估分数波动大或始终达不到预期。排查步骤审视评估标准本身你的评估指标criteria描述是否清晰、无歧义让不同的人根据同一标准打分结果是否一致如果“AI即评估器”的评分不稳定可能是评估指令写得太模糊。检查测试数据质量测试用例是否具有代表性expected_response_contains里的关键词是否过于死板导致模型合理的同义表达被误判考虑加入一些基于语义相似度如余弦相似度的评估而非纯粹的关键词匹配。人工审核定期对评估结果进行人工抽样审核。尤其是那些得分高但你觉得不对或得分低但你觉得还行的案例。这能帮你发现评估体系本身的缺陷。评估器的局限性理解你使用的评估器尤其是LLM作为评估器的偏见和局限性。它可能在某些主观维度如“友好度”上评分不准。对于关键指标考虑结合多种评估方法。最后再分享一个小技巧建立一个“问题案例库”。每次遇到一个棘手的、导致对话失败的案例都把它记录下来包括用户输入、完整的工作流日志、错误信息以及最终的修复方法。这个库不仅是团队宝贵的知识积累未来也可以直接作为“反面教材”加入你的测试数据集确保同样的问题不会再次发生。维护好这个库你的对话系统就会像一个有经验的老兵一样越战越强。