# 智能问答模块软件需求说明书 ## 1. 总体概述 - 本系统外挂在现有 BI 平台,负责解析仪表板、卡片以及机构(bbk)维度下的问答需求,自动生成 SQL 并在 BI 系统中执行。 - 系统提供 FastAPI 后端接口,供前端或其他服务发起“问题生成/确认”流程,并将确认后的问答对写入 parquet 文件,用于离线训练或直接答复。 - 全部服务运行在后台,无前端组件;所有对话上下文均来源于 DuckDB 中的 BI 元数据表及机构配置。 ## 2. 数据结构要求 1. **卡片-数据集-仪表板映射表**:字段 `card_id、dashboard_id、dataset_id、dashboard_name、card_name、dataset_name、bbk_id`。作为主数据表,保证数据有效。 2. **卡片信息表**:字段 `card_id、card_name、card_desc、sql_select、sql_where、sql_groupby` 描述卡片的 SQL 形态。 3. **卡片筛选器信息表**:字段 `card_id、filter_id、filter_type(F/D)、where_clause、default_value、options` 描述可选筛选器与内置过滤条件。 4. **仪表板信息表**:字段 `dashboard_id、dashboard_name、dashboard_desc、folder_path` 描述仪表板元数据。 5. **数据集 DDL 表**:字段 `dataset_id、dataset_ddl`,按 HiveSQL 规范存放。 这些结构均存放于 DuckDB,所有查询均基于机构编号(bbk/bbk_id)过滤。 ## 3. 系统架构 - **接口层**:`app/endpoints` 下的 FastAPI `generate_qa_pair` 接口作为唯一对外入口。 - **工作流层**:`PipelineManager` + `Workflow` 负责解析配置化节点依赖,并串联 operator。 - **Operator 层**:`generate_qa_pair` operator 协调数据读取、prompt 渲染、LLM 调用与结果解析。 - **支撑模块**: - `LLMManager` 统一管理不同模型提供方与解析策略。 - `PromptManager` 负责 prompt 模板的存储、渲染和复用。 - `ParserManager`/`parsers` 定义 LLM 输出解析策略。 - `DuckDBClient` 提供线程安全的数据查询封装。 - 日志模块 `app.log` 负责统一输出。 - 常量模块 `app.const` 维护目录、阈值等。 模块间关系:接口层调用 `Workflow`;`Workflow` 根据配置调用 operator;operator 内部组合数据访问模块、Prompt/LLM 管理器与解析器。最终结果写入日志目录与 parquet 文件。 ## 4. 模块划分与实现要点 ### 4.1 接口模块(FastAPI) - 负责接收 `QARequest`,校验卡片数量不超过 `MAX_INPUT_CARD_IDS`。 - 将 `bbk_id/dashbord/card_ids/user_request` 打包成 `input_args` 交给 `Workflow`。 - 返回 `QAResponse`,包含仪表板、机构、卡片 ID 及问答列表。 ### 4.2 工作流模块 - `PipelineManager`:从 `config/pipeline_settings.yaml` 读取节点定义,生成拓扑顺序。 - `Workflow`:按照拓扑依次执行 operator,支持异步/流式输出。 - 节点之间通过 `workflow.result` 共享数据,`last_node` 节点需写入最终结果。 ### 4.3 Operator:generate_qa_pair - 从 `DuckDBClient` 读取仪表板、卡片、筛选器及 DDL 元数据,组装为 `DashboardInfo`。 - 使用 `PromptManager` 渲染 `generate_qa_pair` 或带用户偏好模板。 - 调用 `LLMManager` 按节点配置选择模型,获取 JSON 问答列表,并借助 `ParserManager` 解析。 - 将过滤条件转换为 WHERE/HAVING 语句,拼接最终 SQL,构造 `QAPair`。 - 记录 prompt 文本和生成结果日志,并触发 parquet 落盘(后续模块负责)。 ### 4.4 LLM 管理模块 - `LLMManager` 为单例,读取 `config/llm_settings.yaml`。 - 支持多种 provider:默认 `echo`(回声,便于测试)、`http`(通过 HTTP 调用自建/第三方 LLM 服务)。 - 每个模型可指定解析器(如 `json`、`text`),通过 `ParserManager` 统一管理。 - 暴露 `get_llm_model(model_name)`,operator 根据 pipeline 配置取用。 ### 4.5 Prompt 管理模块 - `PromptManager` 读取 `config/prompt_template.yaml` 或使用内置默认模板。 - 模板可存放于 `prompts/` 目录或直接配置在 YAML 中,支持变量占位与必填校验。 - `PromptTemplate.ainvoke(context)` 异步渲染并返回文本,供 operator 直接写入日志或传给 LLM。 ### 4.6 解析器模块 - `parsers.BaseParser` 抽象解析器接口。 - 内置 `JsonParser`(去除 Markdown 包裹、解析 JSON)与 `TextParser`(直接返回文本)。 - `ParserManager` 允许通过配置注册自定义解析器或重写默认行为。 ### 4.7 数据访问模块 - `DuckDBClient` 封装了线程安全查询方法,支持: - `fetch_dashboard_cards`:根据 `dashboard_id`、`card_ids`、`bbk_id` 过滤卡片。 - `fetch_card_definition`:获取卡片 SQL 定义。 - `fetch_card_filters`:获取筛选器/固化条件。 - `fetch_dashboard_info`、`fetch_dataset_ddl`:补全仪表板及数据集信息。 - 所有查询返回字段-值 dict 列表,以供 Pydantic 模型构造。 ### 4.8 存储与日志 - 日志目录 `app/log`,通过 `app.log.logger` 写入,支持级别控制。 - Prompt 与问答日志写入 `LOG_ROOT/prompts/...` 便于审计。 - 经过人工确认的问题将由后续节点序列化到 parquet,文件路径遵循 `DATA_DIR/parquet/{bbk_id}/{dashboard_id}/`。 ## 5. 业务流程 1. 用户在 BI 前端选定仪表板、卡片与机构,触发 API。 2. 接口层调用 `Workflow`;`get_dashboard_info` 节点(后续实现)使用 `DuckDBClient` 读取所需元数据。 3. `generate_qa_pair` operator 构建 prompt,调用 LLM 生成若干候选问题和过滤条件。 4. 系统将问答转成 SQL,连同 slot 化问题写入返回体与 parquet,日志记录 prompt 与 SQL。 5. 后续模块可基于这些问答对执行真实查询或训练问答模型。 ## 6. 非功能需求 - **性能**:单次请求支持最多 3 张卡片(可通过常量调整)。DuckDB 查询需在 1 秒内返回元数据。 - **扩展性**:LLM 与 Prompt 均通过配置驱动,可为不同机构配置不同模型或模板。 - **可观测性**:日志必须包含 request_id、bbk_id、dashboard_id 以便审计。 - **安全**:所有外部 LLM HTTP 调用需支持自定义 Header,用于透传鉴权 token。 ## 7. 开发注意事项 - 任何变量或字段中包含 `bbk/bbk_id` 均指机构编号。 - 当 YAML/模板缺失时,模块会回退到默认模板与 Echo LLM,方便在无外部依赖下开发调试。 - DuckDB 表结构需与上述字段保持一致,字段命名采用 snake_case。