bricks/aidocs/wsllm.md
2025-10-05 06:39:58 +08:00

13 KiB
Raw Blame History

bricks.LlmIO 技术文档

本模块实现了一个基于 Web 的多模型 LLM大语言模型交互界面组件支持流式/同步响应、用户输入、语音输出、反馈评分等功能。适用于构建类 ChatGPT 的对话系统。


目录


概述

bricks.LlmIO 是一个复合型 UI 控件,用于集成多个 LLM 模型并统一管理用户输入和模型输出。它提供了以下能力:

  • 支持添加多个 LLM 模型;
  • 用户通过表单提交输入;
  • 支持 流式 (stream)同步 (sync)异步 (async) 响应模式;
  • 输出内容可动态渲染(支持模板化视图);
  • 支持 TTS文本转语音流式播放
  • 可对模型输出进行满意度评分(点赞/踩);
  • 自动维护会话历史(可选);

该组件基于 bricks.js 框架构建,采用面向对象设计,高度可配置和可扩展。


核心类结构

类名 功能
bricks.LlmIO 主容器,管理所有模型实例和输入/输出区域
bricks.LlmModel 单个 LLM 模型的封装,处理请求发送与消息管理
bricks.ModelOutput 显示单条模型输出结果,支持富内容渲染与反馈控件
bricks.RoleOutput (内部基类) 统一用户与模型输出样式布局的基础类

类详解

bricks.LlmIO

主控件,继承自 bricks.VBox,作为整个对话系统的容器。

构造参数 (opts)

{
  ws_url: String,               // WebSocket 地址(预留未使用)
  user_icon: String,            // 用户头像图标 URL
  list_models_url: String,      // 获取可用模型列表的 API 接口
  input_fields: Array,          // 输入表单字段定义(用于 bricks.Form
  input_view: Object,           // 定义如何展示用户输入的内容widget 描述)
  output_view: Object,          // 默认全局输出视图模板(可被模型覆盖)
  models: Array<LlmModelOpts>,  // 初始加载的模型配置数组
  tts_url: String,              // TTS 接口地址(启用语音时使用)
  estimate_url: String,         // 提交反馈评分的接口地址
  msg_css: String               // 用户消息的 CSS 类名(默认 'user_msg'
}

属性

属性 类型 说明
ws bricks.WebSocket 预留 WebSocket 实例(当前未实际使用)
llmmodels Array<bricks.LlmModel> 已添加的模型实例列表
title_w bricks.HBox 顶部显示模型标签的容器
o_w bricks.Filler 输出内容滚动区域
i_w, nm_w bricks.Svg “输入” 和 “新增模型” 图标按钮
textvoice Boolean 是否启用文本语音合成功能

方法

constructor(opts)

初始化主界面,创建标题栏、输出区、底部操作按钮,并加载初始模型。

show_added_model(m)

将给定模型配置 m 实例化为 LlmModel 并加入界面。

  • 若启用了 textvoice,自动注入 TTS 配置。
  • 调用 render_title() 创建模型标签并插入标题栏。
open_search_models(event)

弹出模型选择弹窗(PopupWindow),从服务器拉取可选模型列表。

  • 使用 bricks.Cols 展示模型卡片列表;
  • 点击任一模型触发 add_new_model()
  • 弹窗点击后自动关闭。
add_new_model(event)

接收来自 Cols 的选中模型数据,将其加入 this.models 数组,并调用 show_added_model() 渲染到界面上。

open_input_widget(event)

打开输入表单弹窗,允许用户输入内容。

  • 使用 bricks.Form 构建表单;
  • 表单字段由 input_fields 配置;
  • 提交后触发 handle_input()
handle_input(event)

处理用户输入数据:

  1. 调用 show_input(params) 显示用户输入;
  2. 遍历所有 LlmModel 实例,若其接受 'userinput' 来源,则调用 model_inputed(params) 发起请求。

使用 schedule_once 延迟执行以避免阻塞 UI。

show_input(params)

将用户输入数据根据 input_view 模板渲染成可视化组件,并显示在输出区域左侧(带用户图标)。

  • 支持富文本或结构化数据显示;
  • 添加 CSS 类 user_msg 或自定义类名。

bricks.LlmModel

表示一个具体的 LLM 模型实例,负责请求发送、消息管理和响应解析。

构造参数 (opts)

{
  icon: String,
  model: String,                  // 模型名称
  url: String,                    // 请求后端 API 地址
  output_view: Object|String,     // 输出渲染模板widget 描述)
  params: Object,                 // 固定请求参数
  user_message_format: Object,    // 用户消息格式模板
  system_message_format: Object,  // 系统消息格式模板
  llm_message_format: Object,     // 模型回复消息格式模板
  use_session: Boolean,           // 是否保持会话上下文
  input_from: String,             // 接收输入来源标识(如 'userinput'
  textvoice: Boolean,             // 是否启用 TTS
  tts_url: String,                // TTS 流地址
  response_mode: 'stream'|'sync'|'async'  // 响应模式
}

属性

属性 类型 说明
llmio bricks.LlmIO 所属父容器
messages Array 当前会话的历史消息(遵循 OpenAI 类似格式)
resp_data Object 最终完整响应数据(用于 sync 模式拼接)

方法

constructor(llmio, opts)

初始化模型实例,设置默认消息格式。

render_title()

生成模型标题栏组件HBox包含图标和点击事件绑定未来可用于配置面板

inputdata2uploaddata(data)

将原始输入数据转换为适合发送给后端的格式:

  • 支持 FormData 或普通对象;
  • 自动追加 model, modelinstanceid, modeltypeid, messages 等字段;
  • 若定义了 user_message_format,则按模板格式化用户消息并推入 messages
model_inputed(data)

主入口方法:当收到用户输入时触发。

根据 response_mode 分支处理:

模式 处理方式
stream / async 使用 HttpResponseStream 分块接收流式响应,逐段更新输出
sync 使用 HttpJson 一次性获取完整响应,并整体更新

在流式模式下,每收到一段数据都会调用 chunk_response() 更新 UI。

is_accept_source(source)

判断是否接受指定来源的输入(目前仅支持 'userinput')。

llm_msg_format()

返回模型回复消息的标准格式,默认为:

{ "role": "assistant", "content": "${content}" }
chunk_response(mout, line)

处理流式响应中的每一个数据块:

  • 解析 JSON
  • 过滤空内容;
  • 转义特殊字符;
  • 调用 mout.update_data(d) 实时更新输出;
  • 累积内容至 this.resp_data
chunk_ended()

流式响应结束后,将最终累积的内容按 llm_msg_format 格式化并压入 messages 数组,完成上下文保存。


bricks.ModelOutput

继承自 RoleOutput,专门用于显示 LLM 模型的输出内容

构造参数 (opts)

{
  icon: String,
  model: String,
  estimate_url: String,       // 提交评分的接口地址
  output_view: Object|String, // 输出内容渲染模板
  textvoice: Boolean,
  tts_url: String
}

属性

属性 类型 说明
img bricks.Svg 模型图标
filler bricks.VBox 内容填充区域
run bricks.BaseRunning 加载动画(请求中状态)
estimate_w bricks.HBox 满意度评价组件(点赞/踩)
upstreaming bricks.UpStreaming TTS 流上传器(语音播报)
logid String 日志 ID用于反馈关联

方法

constructor(opts)

初始化输出框:

  • 创建头部模型信息行(图标 + 名称);
  • 创建内容区域(含加载动画);
  • 若是 LLM 角色,创建左右留白;
  • 调用 build_estimate_widgets() 创建评价控件(如果配置了 estimate_url)。
build_estimate_widgets()

构建“结果满意吗?”评价组件:

  • 包含文字提示、“赞”和“踩”SVG图标
  • 绑定点击事件到 estimate_llm(val)
  • 初始隐藏,待有 logid 时再显示。
estimate_llm(val, event)

提交用户评分:

  • 构造 urlwidget 请求描述;
  • 参数包括 logid 和评分值1=满意,-1=不满意);
  • 动态创建 widget 发起请求;
  • 提交后禁用按钮防止重复提交。
update_data(data)

更新输出内容:

  • 移除加载动画;
  • 启动 TTS 流(如有配置);
  • 使用 output_view 模板结合 data 数据构建 UI 组件;
  • 将组件添加到 filler 中;
  • 若存在 logid,显示评价组件。

支持 output_view 为字符串JSON 字符串)或对象。

finish()

结束 TTS 流传输。


bricks.RoleOutput

⚠️ 注意:代码中存在语法错误 —— defautl_icon 应为 default_icon

ModelOutput 的基类,也用于用户输出(但未导出独立类)。统一管理角色输出的布局结构。

共享特性

  • 左侧图标(用户 or LLM
  • 内容区域居中对齐;
  • 左右两侧空白图标占位(实现对话气泡错位效果);
  • 支持动态内容更新。

数据格式说明

output_view 结构

用于定义模型输出的 UI 渲染模板,是一个标准的 bricks.widget 描述对象:

{
  widgettype: "Text",
  options: {
    text: "${content}",
    wrap: true
  }
}

支持变量插值(${xxx}),由 bricks.apply_data(template, data) 替换。

input_view 结构

同上,用于渲染用户输入内容。

消息格式(messages 数组项)

{
  role: 'user' | 'system' | 'assistant',
  content: String
}

可通过 user_message_formatllm_message_format 自定义格式。


事件与回调机制

事件名 触发条件 示例
record_click Cols 中某条记录被点击 添加新模型
submit Form 提交 处理用户输入
click SVG 按钮点击 打开输入窗、添加模型
自定义绑定 likew.bind('click', ...) 提交评分

扩展功能

流式响应支持

通过 HttpResponseStream 实现 SSE 或分块传输解码,实时更新输出。

文本转语音TTS

利用 UpStreaming 组件边生成边播放音频流,提升交互体验。

用户反馈评分

提供“点赞/踩”按钮,收集用户对模型输出质量的反馈。

多模型共存

支持同时运行多个模型,各自独立维护上下文。

模板化渲染

使用 apply_data() 实现数据驱动的 UI 渲染,灵活支持 Markdown、代码块等复杂内容。


使用示例

var llmio = new bricks.LlmIO({
  user_icon: '/icons/user.png',
  list_models_url: '/api/models/list',
  input_fields: [
    { name: 'prompt', type: 'textarea', label: '请输入问题' }
  ],
  input_view: {
    widgettype: 'Text',
    options: { text: '${prompt}', css: 'user-input' }
  },
  estimate_url: '/api/feedback/rate',
  tts_url: '/api/tts/stream',
  models: [{
    model: 'gpt-3.5-turbo',
    icon: '/icons/gpt.svg',
    url: '/api/llm/chat',
    output_view: {
      widgettype: 'Markdown',
      options: { source: '${content}' }
    },
    response_mode: 'stream',
    input_from: 'userinput',
    use_session: true
  }]
});

document.body.appendChild(llmio.dom);

依赖与注册

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

确保该组件可通过工厂方式动态创建:

bricks.widgetBuild({ widgettype: 'LlmIO', options: {...} });

已知问题与改进建议

问题 建议修复
defautl_icon 拼写错误 → 应为 default_icon 修正拼写
optsmodel_inputed 中引用错误(应为 this.opts 修改为 this.opts.use_session
ws 成员未实际使用 删除或补充 WebSocket 支持逻辑
handle_input 中注释掉 await 可能导致并发问题 建议保留 await 或明确使用异步调度

版本信息

  • 编写日期2025年4月
  • 框架版本:bricks.js (假设)
  • 作者Auto-generated from source code

文档完