# AI_Chat_Assistant PRD # AI 聊天助手需求设计文档(产品需求文档 PRD) ### 文档介绍 | 项目 | 信息 | | --- | --- | | 产品名称 | AI Chat Assistant Flutter Plugin | | 版本 | v1.0.0+1 | | 文档版本 | v1.0 | | 创建日期 | 2025-09-23 | | 最近更新时间 | 2025-09-24 | | 产品经理 | (待指定) | | 技术负责人 | (待指定) | | 目标平台 | Flutter (Android / iOS,首期 Android 优先) | | 发布形态 | Flutter 第三方插件(支持示例 App) | ### 修订记录 | 版本 | 日期 | 作者 | 内容 | | --- | --- | --- | --- | | 1.0 | 2025-09-23 | - | 初版功能需求整理 | ## **1. 引言** ### **1.1 文档目的** 本文档旨在定义“AI Chat Assistant Flutter Plugin”项目的详细功能需求、非功能需求、技术架构及项目规划。它为设计、开发、测试及项目相关人员提供了统一的参考依据和验收标准。 ### **1.2 适用范围** 本文档目标读者为:AI Chat Assistant Flutter Plugin 的系统设计人员、开发人员、测试人员、产品经理以及项目管理人员。 ### **1.3 名词解释** | **序号** | **名词术语** | **名词解释** | | --- | --- | --- | | 1 | Flutter Plugin | 一种可复用的代码包,用于为Flutter应用添加特定的原生平台功能。 | | 2 | ASR | Automatic Speech Recognition,自动语音识别,将语音转换为文本。 | | 3 | TTS | Text-To-Speech,语音合成,将文本转换为语音。 | | 4 | SSE | Server-Sent Events,一种服务器向客户端推送数据的技术。 | | 5 | 车控命令 | 通过语音或界面触发的,用于控制车辆功能(如门锁、空调)的指令。 | | 6 | 场景(Scenario)| 不同业务上下文(购车 / 用车) | ### **1.4 统一异常处理** 1. **网络异常**:语音识别或AI对话过程中出现网络错误,应有明确提示(如:“网络连接失败,请检查后重试”),并提供重试选项。 2. **权限拒绝**:当未授予麦克风或音频录制权限时,应引导用户前往系统设置开启权限。 3. **语音识别失败**:返回空文本或低置信度,提示“抱歉,我没有听清,请再说一遍”。(补充:不缓存失败结果。) 4. **命令执行失败**:车控执行失败需双通道反馈(UI + TTS),并显示失败原因或错误类型标签。(补充:通用错误尽量转化为用户友好语义。) ## 2. 产品概述 ### 2.1 产品简介 AI Chat Assistant 是一个集成语音识别、智能对话、车控指令解析与执行、语音反馈渲染于一体的 Flutter 插件。支持“车控助手”与“用车助手”双场景: - 车控助手:支持 20+ 车辆控制命令(如空调、车窗、车门、座椅加热等)。 - 用车助手:基于用户手册 / 知识库进行问答。(包含 保养咨询、能耗优化建议等) - 购车助手:基于厂家的经销政策以及车辆配置信息进行问答 ### 2.2 产品流程图 现有核心流程:用户长按语音按钮 → 权限校验 → 录音 + 识别 → 文本分类 → 路由到问答/车控/错误反馈 → 结果播报与展示。 ```mermaid graph TD A[用户点击语音按钮] --> B[startVoiceInput] B --> C[检查麦克风权限] C --> D[开始录音/ASR] D --> E[实时显示识别结果] E --> F[用户松开按钮] F --> G[stopAndProcessVoiceInput] G --> H[调用reply处理文本] H --> I[文本分类] I --> J{分类结果} J -->|车控命令| K[handleVehicleControl] J -->|普通问答| L[answerQuestion - ChatSseService] J -->|错误问题| M[answerWrongQuestion] K --> N[解析车控命令] N --> O[执行TTS播报] O --> P[执行车控命令] P --> Q[生成执行反馈] Q --> R[更新UI显示] L --> S[SSE流式对话] S --> T[实时TTS播报] T --> R ``` ### 2.3 产品目的 - 提供开箱即用的AI语音交互能力 - 支持自然语言车控命令识别与执行 - 轻量级架构,易于集成和定制 ### 2.4 顶层功能结构 ```mermaid graph LR ASR[语音采集/ASR] --> CLASS[文本/意图分类] CLASS -->|车控| CMD[车控解析/执行] CLASS -->|问答| QA[对话引擎 SSE/WS] CLASS -->|兜底| FALL[引导重试/澄清] QA --> TTS[TTS 播报] CMD --> FEED[执行反馈] TTS --> MSG[消息渲染] FEED --> MSG MSG --> STORE[(本地持久化)] ``` ### 2.5 语音交互主流程 ```mermaid graph TD START[长按/唤醒触发] --> PERM[权限校验] PERM -->|通过| REC[开始录音] PERM -->|拒绝| EXIT[权限引导提示] REC --> ASR[实时增量识别] ASR --> RELEASE[松手/结束] RELEASE --> CLASSIFY[分类/意图识别] CLASSIFY -->|车控| CONTROL[结构化命令] CLASSIFY -->|问答| STREAM[流式对话输出] CLASSIFY -->|无匹配| GUIDE[兜底提示] CONTROL --> EXEC[调用车控处理器] EXEC --> RESULT[结果反馈] STREAM --> MERGE[增量合并/渲染] RESULT --> RENDER[消息渲染 + TTS] MERGE --> RENDER RENDER --> STORE[(持久化过滤保存)] ``` ## 3. 功能需求 ### 3.1 用户页面展示 #### **3.1.1 浮动图标组件(ChatFloatingIcon)** - **用户场景** 在主应用界面上提供一个常驻的、可随意拖拽的AI助手入口,作为全局统一入口,维持轻量可达性,不干扰主业务操作。 - **功能描述** 一个可拖拽的浮动按钮,点击展开全屏聊天界面,长按直接启动语音输入(只有聊天窗口)。 - **需求说明** - **拖拽吸附**:支持在屏幕内自由拖拽,松开时自动吸附到最近的屏幕边缘。 - **交互响应**: - **点击**: 进入全屏的聊天页面,全屏模式为一个新的页面 - **长按**:变为聆听模式,直接开始语音录制,出现聊天窗口 - **位置自适应**:聊天窗口的位置需要根据浮动按钮的位置变化,如果浮动按钮位置过于靠上,则聊天窗口显示在浮动按钮的下方,默认显示在浮动按钮的上方 - **状态指示**:通过动画(如呼吸效果)表示待机、聆听、思考等不同状态。 默认为待机状态,长按会进入聆听状态,思考中的状态会在聊天显示思考中的状态聊天气泡 - **补充说明**:长按阈值建议 300ms;误触策略:短按抬起不触发录音。 ![image.png](images/db1d92f4-107d-46c9-8154-fc58cb471acc.png) ![image.png](images/image.png) #### **3.1.2 浮动聊天窗口(ChatPopup)** - **用户场景** 用户与AI助手进行可视化的文本和语音交互。 - **功能描述** 提供弹出式聊天窗口,展示对话记录并提供输入方式,不承担复杂历史翻阅与批量操作 - **需求说明** 长按浮动按钮即可出现浮动聊天窗口,长按状态下展示聆听中,放开后则聆听结束,变为思考中状态。 思考中状态可以手动点击 **停止回答** 可以终止AI对话,直到回答完成,则不可点击停止回答。 ![Screenshot_20250923_162311.jpg](images/Screenshot_20250923_162311.jpg) ![image.png](images/image%201.png) #### **3.1.3 全屏聊天界面(ChatFullscreen)** - **用户场景** 用户与AI助手进行可视化的文本和语音交互,适用于长对话、多轮引用、查看历史与多类型气泡的交互。 - **功能描述** 提供全屏聊天界面,展示对话记录并提供输入方式。全屏的聊天页面功能更加丰富,多类型气泡、快捷指令区、功能按钮区、历史分页加载 - **需求说明** - 全屏聊天模式下会保留之前浮动聊天窗口的聊天记录 - 不同的场景为不同的AI助手,现有两种场景,购车助手和用车助手(根据入口来判断) - 顶部会有可配置的功能按钮区域(用户服务/购车服务) - 功能按钮下方会有快捷对话的区域,可以点击换一换来更换快捷指令,支持“换一换”刷新策略(本地轮换或服务侧下发) - 聊天页面底部会有功能栏,分别为**删除当前对话**,**按住说话**,**切换文本输入** - 如果存在本地对话记录,点击 **显示历史对话记录** 会加载之前的5条对话记录,同样可以通过上拉来加载历史对话记录 ![image.png](images/image%202.png) ### 3.2 AI对话场景 #### **3.2.1 购车助手场景** - **用户场景** 用户未绑定车辆的情况下,爱车页面变为购车页面,购车页面也会有AI助手,未绑定车辆用户获取车型配置、优惠、推荐。 - **功能描述** 购车页面的AI助手没有聆听模式,只能点击进入全屏的聊天页面,首次的回复词也会有变化;功能按钮区域和快捷回复区域都会跟用车助手不同 - **需求说明** - 浮动按钮点击可进入全屏的AI助手页面,顶部的功能按钮为热门车型推荐,同样是icon+text的按钮,点击之后会快捷输入车型的名称,AI助手会回复车型的相关信息,同时快捷对话的区域会按照对话来进行变化; - 购车助手同样可以通过文本的语义来进行推荐车型,以及解读购车的优惠信息; - 如果在购车助手场景下,本身并没有绑定车辆,如果有车控的语音输入,则返回:您还未绑定车辆,无法使用车控指令; - 如果是用车助手场景,包含购车助手的全部功能,同样可以回复相应车型来获取配置信息以及购车政策。 ![image.png](images/image%203.png) ![image.png](images/image%204.png) #### **3.2.2 用车助手场景** - **用户场景** 用户在绑定车辆的情况下,进入爱车页面,使用AI助手则我用车助手场景 - **功能描述** 用车助手场景下的AI助手不同于购车场景,可以按照文本的输入分为三种:普通问答,车控指令,错误问题反馈 - **需求说明** - 用车场景下的功能按钮为官方推荐,内容包括智能场景推荐、数据埋点和运营位,其中智能场景推荐包括售后维保提醒,智能场景建议;数据埋点包括能耗报告,行为分析,用户习惯操作;运营位则是推荐的车型,用户复购建议; - 常见功能按钮 → 发送一条“功能集合”消息气泡(含多个按钮)。 - 点击 更多工具按钮跟常见功能按钮一样,会返回一条聊天记录,里面会包含多个按钮,点击按钮可以进行快捷回复; - 快捷回复区域是可以变化的,会根据对话的最后一个回复进行变化,快捷回复区域会跟在最后一个对话的底部;例如刚进入会跟在 功能按钮的底部,但是新的聊天记录出现后,就会自动拼接到聊天气泡的底部(聊天气泡类型分为多种,后面会详细介绍); ![image.png](images/image%202.png) #### **3.2.3 用户唤醒场景** - **用户场景** 在开通语音唔醒功能之后,购车页面和爱车页面都可以使用语音唤醒,免手动触发,提高便利性 - **功能描述** 用户可以通过语音唤醒功能在不需要点击按钮的情况下激活AI助手,提高使用便捷性和用户体验。唤醒词“你好,众众”,唤醒后直接进入聆听模式并高亮反馈。 - **需求说明** - 设置页开启后常驻监听(低功耗策略)。 - 唤醒检测在本地执行,未唤醒音频不上传。 - 唤醒成功:音效 + 动画反馈。 - 低电量模式:可自动降敏或暂停。 - 权限缺失:首次引导开启麦克风权限。 ### 3.3 聊天模块 #### **3.3.1 聊天气泡类型** - **用户场景** 用户与AI助手对话过程中,会展示不同类型的聊天气泡以适应各种交互需求。 - **功能描述** 系统支持多种聊天气泡类型,包括文本气泡、卡片气泡、按钮气泡、链接气泡和富媒体气泡等,以满足不同场景下的交互需求。 - **需求说明** - 文本气泡:展示普通文字对话内容,完整支持Markdown格式; Markdown支持包括普通文本格式化、表格布局以及图片嵌入,提供更丰富的内容展示方式 - 卡片气泡:用于展示结构化信息,如车辆信息、维保记录等; - 按钮气泡:包含可交互按钮,用于快速回复或执行操作; - 富媒体气泡:支持图片、视频、语音等多媒体内容展示; 富媒体气泡可能适用于显示特定的信息,或者是视频的教程,轮播的图片 - 链接气泡:用于显示一个链接,包含Icon,Title,Description,以及一个可以点击的链接; 点击链接可以进入webview,链接气泡主要是用于详细介绍某些活动或者查看详情 - 业务气泡:用于特定业务的定制化气泡,会根据对话的业务场景,显示不同的气泡。 业务气泡不同于其他的气泡,可以在用户询问金融方案后显示返回的计算结果,在结果后面还有一个按钮,可以进入金融计算器的页面;同时在用户说出我希望订购某款车型时,会出现车型的信息,并且有一个立即订购的按钮。业务气泡是根据返回的数据来判断具体的业务场景,混合显示的气泡类型。 ![按钮气泡](images/button_bubble_image.png) ![快捷回复](images/quick_reply_image.png) ![业务气泡1](images/image%203.png) ![业务气泡2](images/bussine_image.png) ![聊天气泡](images/bubble_image_list.png) #### **3.3.2 普通问答流程** - **用户场景** 用户与AI助手对话过程中,AI助手会把语音转换为文本,通过文本的语义来判断场景,是普通问答或者是车控指令 - **功能描述** 普通问答现在只有用车助手这个场景,后续增加新的场景:购车助手;需要先通过文本语义判断是哪个场景,然后根据相应场景来回复问题。 - **需求说明** - 场景识别由后端完成,前端仅消费分类结果 - SSE:按流片段累积,合并为 Markdown 不管是购车场景还是用车场景,或者是开放式对话,都有一个问答的流程,场景的区分不是前端来判断。现在流程是将语音转化的文本通过接口发给后台服务,然后后台会根据body里面的text和conversation_id 来返回一个文件流,客户端这边会把文件流的全部数据接受完成后合并为一个markdown语法的文本。 ```mermaid graph TD A[文本数据] --> B{Chat api} B --> C[文件流] --> D{SSE Service} --> E[Markdown文本] E --> F{TTS} --> G[播放语音] E --> H{Message} --> I[显示] ``` 现在有两个新的调整方案,一个是Socket连接,另外一个方案是在现有的流程基础上新增消息类型。 1. Socket方案 每次进入AI助手会话会创建一个随机的taskId,然后每次对话都会有一个conversationId,使用taskId 连接Socket成功后,就可以通过Socket发送语音或者文本消息。然后Socket 会返回三种不同的消息类型,`it消息 (识别文本)`,`gb消息 (回复文本)`,`tts消息 (语音数据)`。 流程图如下: ```mermaid sequenceDiagram participant C as 客户端 participant S as 服务器 Note over C, S: 第一步:建立WebSocket连接 C->>S: WebSocket Handshake (携带认证信息) Note over C, S: 第二步:客户端发送语音数据 C->>S: 发送消息: {taskId, conversationId, audioData} Note over C, S: 第三步:服务器异步返回多条消息 par 并行处理与推送 S-->>C: it消息 (识别文本) and S-->>C: gb消息 (回复文本) and S-->>C: tts消息 (语音数据) end Note over C, S: 连接保持,可继续发送新语音或关闭 ``` 2. HTTP方案 HTTP方案是保持原有流程的情况下进行扩展,chat API 不再是返回一个数据流,而是返回一个json数据,json数据里面会有不同的消息返回,对应上面不同的气泡类型,消息类似分为`stream`,`text`,`media`,`bussines`,`stream`消息就是之前的数据流的消息,通过`messageId`就可以获取到数据;`text`消息是普通的文本消息,可以实现上面的链接气泡,按钮气泡;`media`消息则可以实现负责的图文混排,或者是一个单纯的视频教程;`bussines`消息主要以业务相关的,会根据业务类型显示不一样的样式,内容和按钮也会有变化。 ```json { "conversationId": 1, "taskId": "task_123", "code": 200, "scenario": "buying_assistant", "messageList": [ { "messageId": "messageId_xxxxx", "type": "stream" }, { "messageId": "messageId_xxxxx", "type": "text", "content": "xxxxx" }, { "messageId": "messageId_xxxxx", "type": "media" }, { "messageId": "messageId_xxxxx", "type": "bussines", "bussineType": "vehicle_commendation" }, ] } ``` #### **3.3.3 车控指令流程** - **用户场景** 用户与AI助手对话过程中,AI助手会把语音转换为文本,通过文本的语义来判断场景,是普通问答或者是车控指令 - **功能描述** 如果根据分类结果,将语音或者文本信息归类为车控指令,则会进入车控指令的流程。识别语音指令中的车控意图,解析参数,并调用相应的车辆控制接口。 - **需求说明** - **命令识别**:支持识别20+种车控命令类型。 - **参数解析**:能从指令中解析出关键参数(如温度值、座椅位置)。 - **执行反馈**:命令执行成功或失败,都必须有明确的TTS和UI反馈。 - **可扩展性**:提供抽象类`VehicleCommandHandler`,允许开发者根据具体车型实现自定义控制逻辑。 - **支持命令示例**: - **车门控制**:上锁、解锁 - **车窗控制**:开启、关闭 - **空调控制**:开启、关闭、温度调节、极速降温 - **座椅控制**:主/副驾驶座椅加热、通风 - **后备箱控制**:开启、关闭 - **特殊功能**:鸣笛、车辆定位、一键备车、一键融雪 #### **3.3.4 聊天信息持久化** - **用户场景** 用户在与AI助手进行对话时,会产生多条聊天记录。为保护用户隐私和提升体验,这些聊天记录默认仅保存在本地设备,不会上传至云端。 - **功能描述** 系统支持本地化持久化存储普通问答类型的聊天记录。所有文本类消息将以结构化数据形式保存至本地数据库(推荐使用SQLite或Hive等Flutter主流轻量级数据库),便于后续检索和管理。 - **需求说明** - **本地存储**:所有与AI助手的聊天记录(包括文本、语音、气泡类型、时间戳等)需保存在本地设备,支持持久化; - **存储方式**:采用本地数据库(如SQLite、Hive等Flutter常用方案),或文件存储,保证数据安全和高效读写; - **读取与展示**:用户重新进入聊天界面时,不会自动加载历史聊天记录,点击显示历史记录之后才会加载聊天记录,按时间顺序展示; - **数据结构**:每条聊天记录需包含:消息ID、会话ID、消息类型(文本/语音/卡片/按钮/富媒体)、内容、时间戳、发送方(用户/AI)、气泡类型等; - **删除与清理**:支持用户手动删除单条或全部聊天记录,支持定期自动清理(如超过30天自动删除); - **持久化逻辑**:在Socket和HTTP两种消息方案下,收到消息体后,系统会优先将stream和text类型消息持久化保存,其他类型消息仅用于即时展示,不做持久化处理。 有了消息的持久化,AI助手聊天消息的显示逻辑也会跟着变化,按照上面的`Socket`方案和`HTTP`方案,收到消息体之后首先会保存到本地,特别是`HTTP`方案中会有多条消息返回,持久化只会保存stream和text消息,其他消息不会保存。 ```mermaid graph TD A[收到AI助手消息] --> B[显示消息到聊天界面] B --> C{消息类型判断} C -->|stream/text| D[持久化保存到本地数据库] C -->|其他类型| E[仅显示,不持久化] D --> F[历史消息管理] F --> G[用户点击显示历史记录] G --> H[加载历史消息并展示] ``` ## 4. 非功能需求 ### 4.1 服务模块 #### **4.1.1 模块设计目标** 服务模块负责“输入 → 解析 → 对话/车控 → 反馈 → 持久化”全链路的能力封装,向上提供简单一致的编程接口,向下屏蔽多种后端形态(HTTP / SSE)与原生能力(录音、TTS、权限、ASR)。 设计目标: - 解耦:各服务单一职责,可独立替换; - 可扩展:新协议 / 新命令 / 新气泡类型通过注册或策略扩展; - 可裁剪:按需选择(如不需要车控,可不接入 command 子模块)。 #### **4.1.2 模块目录设计** 拟将现有核心服务抽离为独立基础包(例如:ai_chat_core),供 UI 插件依赖。 建议目录结构: ``` packages/ ai_chat_core/ lib/ ai_chat_core.dart # 对外统一入口 src/ # 代码目录 models/ # models message.dart # 消息和消息块 message_chunk.dart vehicle_command.dart # 车控 vehicle_command_response.dart command_result.dart enums/ # enums message_type.dart message_status.dart command_type.dart service_state.dart # 服务状态 input/ audio_recorder_service.dart # 录音以及保存文件 voice_recognition_service.dart # 目前项目未使用 wake_word_service.dart # 预留(可选) nlp/ # 自然语言处理相关 text_classification_service.dart vehicle_command_service.dart dialog/ #对话相关的 chat_channel/ chat_sse_service.dart # SSE chat_ws_service.dart # 预留 WebSocket(可选) chat_http_service.dart # 批量 HTTP 方案(可选) message_service.dart # 核心编排/状态更新 tts/ # TTS tts_service.dart tts_task_queue.dart command/ # 车控相关 command_service.dart # Command Register Callback(已更新为抽象类的方式) vehicle_command_handler.dart # 自定义实现车控命令 persistence/ # 持久化 persistence_service.dart # 提供持久化服务 dao/ # dao message_dao.dart # 消息体的 dao 对象 infra/ # infra 的服务 config_service.dart redis_service.dart location_service.dart vehicle_state_service.dart # 预留 logger.dart error_mapper.dart utils/ # 工具类 markdown_cleaner.dart id_generator.dart throttle.dart ``` 对外暴露(ai_chat_core.dart)仅导出: - models / enums - MessageService(主入口) - VehicleCommandHandler 抽象 - 配置初始化(initCore / setConfig) #### **4.1.3 核心服务说明** | 服务 | 角色 | 主要职责 | 关键点 | | ---- | ---- | -------- | ------ | | MessageService | 总编排 | 状态机、消息生命周期、调用链调度 | 统一入口 | | AudioRecorderService | 输入 | 录音启动/停止、静音检测 | 录制参数配置 | | VoiceRecognitionService | 输入处理 | 语音转文本(在线识别 / 中英判别) | 失败降级提示 | | WakeWordService | 输入唤醒 | 本地唤醒词检测 | 低功耗策略 | | TextClassificationService | 语义分类 | 业务场景 / 指令 / 问答判断 | 分类缓存 | | VehicleCommandService | 语义→结构 | 解析多条车控命令列表 + 参数 | 容错解析 | | CommandService | 执行派发 | 调用 Host 注入的 VehicleCommandHandler | 失败重试 | | ChatSseService | 对话通道 | SSE 流接收与分片回调 | 首 Token 优化 | | ChatWsService(预留) | 对话通道 | WebSocket 统一多类型消息 | 心跳+重连 | | ChatHttpService(预留) | 对话通道 | 一次性批量消息 | 并行补拉 | | TtsService + TtsTaskQueue | 输出播报 | 分句 / 排队 / 抢占 / 语言切换 | 顺序一致性 | | PersistenceService | 持久化 | 消息落地 / 分页 / 过期清理 | schema 迁移 | | RedisService | 辅助缓存 | 临时状态(可选) | 可替换 | | LocationService | 扩展 | 位置信息(用于上下文) | 可选注入 | | VehicleStateService | 扩展 | 实时车况(未来支持) | 监听通道 | | ConfigService | 基础设施 | 端点 / 超时 / 重试策略统一 | 环境隔离 | | Logger | 基础设施 | 分级日志 + 调试开关 | 生产开关 | | MarkdownCleaner | 工具 | 清理/裁剪 Markdown 用于 TTS | 多语言规则 | | ErrorMapper | 工具 | 后端错误码 → 用户友好文案 | 本地化适配 | #### **4.1.4 服务分层** - 链路图 ```mermaid sequenceDiagram autonumber participant UI as UI层 participant MS as MessageService participant AR as AudioRecorder participant ASR as VoiceRecognition participant CLS as TextClassification participant VCS as VehicleCommandService participant DLG as ChatSse/WS/HTTP participant CMD as CommandService participant HND as VehicleCommandHandler(Host) participant TTS as TtsService participant PERS as PersistenceService UI->>MS: startVoiceInput() MS->>AR: start() AR-->>MS: audioChunks / silenceEnd MS->>AR: stop() MS->>ASR: recognize(audio) ASR-->>MS: recognizedText MS->>CLS: classify(text) CLS-->>MS: category / scenario alt 车控指令 MS->>VCS: parseCommands(text) VCS-->>MS: commands[] loop each command MS->>CMD: execute(command) CMD->>HND: executeCommand(command) HND-->>CMD: result(success/fail) CMD-->>MS: executionResult MS->>TTS: enqueue("执行结果反馈") MS->>PERS: save(control_feedback) end else 普通问答 MS->>DLG: requestStream(text, convId) DLG-->>MS: streamChunk/ finalMessage MS->>TTS: enqueue(chunk/segments) MS->>PERS: save(text / merged) else 错误/兜底 MS->>TTS: enqueue(提示语) MS->>PERS: save(system_message) end TTS-->>UI: 播放中事件 PERS-->>MS: persist OK MS-->>UI: 更新消息列表 ``` - 逻辑分层 ```mermaid graph TD A[UI层] --> B[MessageService] B --> C1[输入层 AudioRecorder / WakeWord] B --> C2[语义层 Classification / VehicleCommand] B --> C3[对话通道层 SSE / WS / HTTP] B --> C4[执行层 CommandService + Host Handler] B --> C5[输出层 TtsService] B --> C6[存储层 PersistenceService] B --> C7[基础设施 Config / Logger / Redis / Location] ``` #### **4.1.5 代码示例** - 初始化: ```dart await AiChatCore.init( config: CoreConfig( endpoints: Endpoints( classify: "...", sse: "...", ws: "...", controlParse: "...", controlExec: "...", voice: "...", ), timeouts: Timeouts(connectMs: 8000, receiveMs: 20000), enablePersistence: true, persistenceMode: PersistenceMode.hive, retryPolicy: RetryPolicy(maxAttempts: 2, backoffBaseMs: 400), ), commandHandler: MyVehicleCommandHandler(), logger: CustomLogger(), ); ``` - 统一公共接口: ```dart abstract class AiChatCore { static Future init({required CoreConfig config, required VehicleCommandHandler commandHandler, Logger? logger}); static MessageService get messageService; static PersistenceService? get persistence; } class MessageService { Stream> get messageStream; Future startVoiceInput(); Future stopAndProcessVoiceInput(); Future sendText(String text); Future abortAnswer(); Future loadHistory({required int page, required int pageSize}); } ``` #### **4.1.6 编译与分发说明(path 子包 vs 单包)** - 当前结构:插件(ai_chat_assistant)+ 仓库内 path 依赖(packages/ai_chat_core、packages/basic_intl)。 - 下游集成(pubspec)仅需: ```yaml ai_chat_assistant: git: url: ref: ``` - Flutter 构建行为: 1. 克隆仓库 → 解析主插件 pubspec → 解析 path 子包 → 汇总全部 Dart 源码。 2. Debug:JIT,Release:统一 AOT 编译为一个 snapshot(无包边界差异)。 - 性能与产物差异:将子包“内联”进 lib/ 与保持 path 组织,在编译后无本质差异(tree shaking 后输出等价)。 - 适用场景对比: | 目标 | 保持多包 | 合并单包 | | ---- | -------- | -------- | | 代码隔离 / 复用 | 优 | 弱 | | 发布到 pub.dev | 需逐包发布 | 更简单 | | 测试隔离性 | 优 | 一般 | | 用户认知成本 | 稍高 | 低 | - 暂不需发布:保持 path 结构即可;若未来开放生态 → 发布次序:ai_chat_core → basic_intl → ai_chat_assistant。 #### **4.1.7 AAR 与闭源分发说明** | 诉求 | 可行性 | 说明 | | ---- | ------ | ---- | | 给“另一个 Flutter App”仅提供预编译 AAR 使用 | 不推荐/不可行 | Flutter 仍需源文件参与整体编译流程 | | 给纯原生 Android App 内嵌使用 | 可用 `flutter build aar` | 适用于“原生 App 集成 Flutter 模块”,不是插件分发 | | Dart 逻辑闭源 | 官方未支持 | 只能转移核心到 native/FFI 或服务端 | 结论:对 Flutter 使用方,直接 Git 依赖即可,无需 AAR。 --- ## 参考文件 > [AI Assistant in One App.pdf](https://telekom-my.sharepoint.de/:b:/r/personal/guangfei_zhao_t-systems_com/Documents/Dokumente/AI%20Assistant%20in%20One%20App.pdf?csf=1&web=1&e=On4V2o) > [Figma 设计稿](https://www.figma.com/design/04VXNLNrLdVDHhKBuOr06o/AI_Chat_Assistant?node-id=2-4607&t=qofYGMFzBLQ7cKus-1) > [分子送检系统需求规格书.docx](images/%E5%88%86%E5%AD%90%E9%80%81%E6%A3%80%E7%B3%BB%E7%BB%9F%E9%9C%80%E6%B1%82%E8%A7%84%E6%A0%BC%E4%B9%A6.docx)