bricks/docs/cn/llm.md
2025-10-12 17:59:59 +08:00

12 KiB
Raw Blame History

以下是针对您提供的 JavaScript 代码编写的 Markdown 格式技术文档,结构清晰、注释完整,适用于前端开发团队或项目维护者使用。


📘 bricks.LlmIO 模块技术文档

基于 bricks.js 框架实现的多模型大语言模型LLM交互系统
支持流式响应、文本转语音TTS、用户反馈评分等功能


🔧 模块结构概览

bricks = window.bricks || {}
bricks.LlmMsgAudio     // 音频播放与流式消息处理
bricks.ModelOutput     // 模型输出 UI 组件
bricks.LlmModel        // 单个 LLM 模型控制器
bricks.LlmIO           // 主控容器:管理输入、多个模型和输出展示

所有组件均继承自 bricks.js 提供的基础 UI 类(如 VBox, HBox, JsWidget 等),并支持动态构建、事件绑定和异步数据流处理。


1. bricks.LlmMsgAudio —— 流式音频消息处理器

功能说明

用于处理来自后端的流式文本响应,并根据标点符号分段发送至音频播放器。自动检测语言以适配中英文标点。

继承关系

class LlmMsgAudio extends bricks.UpStreaming

构造函数:constructor(opts)

参数 类型 描述
opts Object 传递给父类的配置项

初始化字段:

  • this.olddata: 上一次接收到的数据(用于增量比较)
  • this.data: 当前累积的完整文本
  • this.cn_p: 中文标点符号数组 [“。”,”,”,”!”,”?”,”\n”]
  • this.other_p: 英文标点符号数组 [“.”,”,”,”!”, “?”, “\n”]
  • this.audio: 实例化的音频播放器(通过 AudioPlayer({}) 创建)

方法列表

detectLanguage(text)String

尝试使用浏览器内置的 Intl.LocaleDetector 推测文本语言。

  • 返回示例:'zh', 'en'
  • 若失败则返回 '未知'

⚠️ 注意:Intl.LocaleDetector 并非所有浏览器都支持,需注意兼容性降级处理。

send(data)void

接收增量数据并进行分句处理,将已完成句子通过 super.send() 发送。

工作流程:
  1. 计算新增部分:newdata = data.slice(this.olddata.length)
  2. 更新历史数据缓存
  3. 调用 detectLanguage(this.data) 判断语言
  4. 使用对应标点分割成句子数组(过滤空字符串)
  5. 将除最后一句外的所有完整句子发送出去
  6. 保留最后未完成句在 this.data 中等待下一批数据

💡 示例:
输入 "你好!今天天气" → 输出 "你好!",缓存 "今天天气"

async go()Promise<Response>

调用父类 go() 获取最终响应,并设置音频源为该响应内容。

await super.go(); 
this.audio.set_source_from_response(resp);

通常用于非流式场景下的 TTS 音频播放。


2. bricks.ModelOutput —— 模型输出 UI 控件

功能说明

显示单个模型的输出结果,包含图标、加载动画、内容区域及满意度评价功能。

继承关系

class ModelOutput extends bricks.VBox

构造函数:constructor(opts)

属性 类型 必填 默认值 说明
modelname String - 显示的模型名称
icon URL/String llm.svg 自定义图标路径
response_mode String - 可选 'stream', 'sync', 'async'
estimate_url URL - 用户反馈提交地址

内部组件初始化:

  • img: 模型图标 SVG
  • content: 主体 HBox 容器
  • run: 加载动画组件(BaseRunning
  • filler: 实际内容显示区(LlmOut 组件)
  • estimate_w: 满意度打分组件(点赞/踩)

核心方法

build_estimate_widgets()void

创建“结果满意吗?”评分控件(仅当 estimate_url 存在时)。

包含:

  • 文本提示:“结果满意吗?”
  • 👍 点赞图标(绑定 estimate_llm(1)
  • 👎 点踩图标(绑定 estimate_llm(-1)

初始状态为隐藏(.hide()),可在完成后显示。

async estimate_llm(val, event)Promise<void>

用户点击点赞/点踩时触发,向服务端上报评分。

请求参数:

{
  "widgettype": "urlwidget",
  "options": {
    "url": this.estimate_url,
    "params": {
      "logid": this.logid,
      "value": val  // 1 或 -1
    }
  }
}

执行后禁用评分按钮防止重复提交。

async update_data(data)Promise<void>

更新模型输出内容。

  • 移除加载动画 run
  • 调用 filler.update(data) 渲染内容
  • 支持流式逐步更新

finish()void

生命周期钩子,当前无实际逻辑,可扩展。


3. bricks.LlmModel —— 单个 LLM 模型控制器

功能说明

封装一个 LLM 模型的行为逻辑,包括请求发送、格式化、响应处理等。

继承关系

class LlmModel extends bricks.JsWidget

构造函数:constructor(llmio, opts)

参数 类型 说明
llmio LlmIO 实例 上层控制容器引用
opts Object 模型配置对象

配置项 (opts) 支持字段:

字段 类型 说明
model String 模型标识符(如 gpt-3.5-turbo
modelname String 显示名
url URL 请求接口地址
params Object 固定请求参数
input_from String 允许的数据来源标签
textvoice Boolean 是否启用 TTS 语音播报
tts_url URL TTS 接口地址
response_mode String 'stream' | 'sync' | 'async'
icon URL 图标路径

核心方法

render_title()HBox

生成顶部标题栏(含图标),点击可打开设置面板(预留接口)。

show_setup_panel(event)void

待实现:点击标题弹出模型配置面板。

inputdata2uploaddata(data)FormData \| Object

将输入数据转换为适合上传的格式,并注入模型相关信息。

  • 若是 FormData,使用 .append() 添加字段
  • 否则直接赋值对象属性
  • 注入 modelllmid

特殊逻辑:若 llmio.model_inputed 为真,则不添加 model 字段(避免重复)

async model_inputed(data)Promise<void>

主入口方法:接收用户输入并发起模型请求。

行为分支:

模式 行为
'stream' / 'async' 使用 HttpResponseStream 处理流式响应
'sync' 使用 HttpJson 发起同步 POST 请求

流程:

  1. 创建 ModelOutput 显示组件并加入页面
  2. 准备请求数据
  3. 根据模式发起请求
  4. 流式情况下逐块调用 chunk_response(mout, line)

is_accept_source(source)Boolean

判断是否接受来自指定源的数据。

llm_msg_format()Object

返回默认的消息结构模板:

{ role: 'assistant', content: "${content}" }

可用于格式化聊天记录。

chunk_response(mout, l)void

处理每一个流式响应片段(每行 JSON 字符串)。

  • 去除空白字符
  • 尝试解析 JSON
  • 异步模式下只处理 status === 'SUCCEEDED' 的消息
  • 调用 mout.update_data(d) 更新 UI

chunk_ended()void

流结束回调(目前仅打印日志)


4. bricks.LlmIO —— 主控容器LLM 输入输出管理器)

功能说明

集成式组件,提供以下能力:

  • 多模型管理
  • 输入表单弹窗
  • 模型选择弹窗
  • 自动渲染模型输出
  • 支持 TTS 和用户反馈

继承关系

class LlmIO extends bricks.VBox

构造函数:constructor(opts)

属性 类型 说明
user_icon URL 用户头像图标
list_models_url URL 获取可用模型列表的接口
input_fields Array 表单字段定义(参考 bricks.Form
models Array 初始已添加的模型列表
tts_url URL TTS 接口地址
estimate_url URL 用户反馈提交地址

初始化行为:

  • 创建标题栏 title_w
  • 创建输出区域 o_w(滚动容器)
  • 创建底部操作按钮:
    • i_w: 输入按钮(打开输入表单)
    • nm_w: 添加模型按钮(打开模型搜索窗口)
  • 绑定点击事件
  • 若模型少于 2 个且存在 tts_url,启用 textvoice 模式
  • 遍历 models 初始化每个 LlmModel

核心方法

async show_input(params)Promise<void>

显示用户输入内容在对话区域上方。

  • 构建 UserInputView 显示输入数据
  • 添加用户头像图标
  • 插入到 o_w 容器中

show_added_model(m)void

注册一个新的模型实例并将其标题添加到顶部工具栏。

  • 若启用了 textvoice,自动注入 tts_url
  • 实例化 LlmModel
  • 调用 .render_title() 并加入 title_w

async open_search_models(event)Promise<void>

打开“选择模型”弹窗,从远程获取模型列表。

使用 PopupWindow + Cols 组件展示表格形式的模型列表。

表格列定义:

  • 图标 + 名称HBox
  • 描述、启用时间VBox 内嵌 Text

点击某条记录会触发:

  • add_new_model(event)
  • 并关闭弹窗

async add_new_model(event)Promise<void>

将选中的模型加入 this.models 数组,并调用 show_added_model 显示。

async open_input_widget(event)Promise<void>

打开输入表单弹窗。

使用 Form 组件加载 input_fields 定义的字段。

提交后触发:

  • handle_input(event)
  • 并自动关闭弹窗

async handle_input(event)Promise<void>

处理用户提交的输入数据。

  1. 调用 show_input(params) 显示输入内容
  2. 遍历所有 llmmodels,调度执行各自的 model_inputed(params)
    • 使用 schedule_once(fn, 0.01) 实现微任务延迟执行

📦 注册组件

bricks.Factory.register('LlmIO', bricks.LlmIO);

允许通过工厂方式动态创建此组件。


🎯 使用示例

var llmio = new bricks.LlmIO({
  user_icon: '/static/icons/user.png',
  tts_url: '/api/tts',
  estimate_url: '/api/feedback',
  input_fields: [
    { name: 'prompt', label: '输入提示', type: 'textarea' }
  ],
  models: [
    {
      model: 'qwen-plus',
      modelname: '通义千问',
      url: '/api/llm/stream',
      response_mode: 'stream',
      icon: '/icons/qwen.svg'
    }
  ]
});

🛠️ 注意事项 & 待优化点

问题 建议修复
detectLaguage 拼写错误 应为 detectLanguage
this.oter_p 拼写错误 应为 this.other_p
lang='zh' 错误地使用了赋值而非比较 应改为 lang === 'zh'
objcopy 函数未定义 应替换为 JSON.parse(JSON.stringify(data)) 或引入深拷贝工具
Intl.LocaleDetector 兼容性差 建议降级为基于关键词的语言识别算法
schedule_once(..., 0.01) 不标准 建议改用 setTimeout(fn, 0)queueMicrotask

📚 附录关键类图UML 简化版)

+------------------+
|     LlmIO        |
+------------------+
       |
       v
+------------------+
|   LlmModel[x]    |
+------------------+
       |
       v
+------------------+
|  ModelOutput     |
+------------------+---> LlmMsgAudio (用于音频)
       |
       v
+------------------+
|    UserInput     |
+------------------+

📝 总结

本模块实现了完整的 LLM 交互链路:

  1. 用户输入 → 表单收集
  2. 多模型并发调用 → 支持流式/同步
  3. 分句播放音频 → 提升听觉体验
  4. 用户反馈机制 → 支持效果评估闭环

适合集成于智能客服、AI 助手、教育平台等需要多模型对比或语音播报的应用场景。


文档版本v1.0
📅 最后更新2025年4月5日
👨‍💻 编写Bricks Framework Team