Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ai-chat-sdk

iTick AI Chat SDK — 为金融资讯平台提供即插即用的 AI 对话能力。

核心特性

  • ShadowDOM 样式隔离 — 组件样式完全隔离,不受宿主页面 CSS 影响
  • 虚拟滚动 — 支持万级消息量的高性能渲染
  • Markdown 渲染 — 内置 GFM 格式渲染,支持表格、代码高亮、流式输出
  • 多语言 — 内置简体中文、繁体中文、英文
  • 主题切换 — 支持亮色/暗色/跟随系统三种模式
  • 双模式 — 极速模式(fast)与智能分析模式(think),支持运行时切换
  • 流式 SSE — 基于 Server-Sent Events 的实时流式输出,支持取消
  • 消息分段 — 支持 think 与 content 交替流式输出,每个 think 模块独立状态
  • 框架无关 — 核心纯 TypeScript,同时提供 React / Vue 3 封装

安装

# 核心包(必需)
npm install @itick/chat-core

# React 封装(可选)
npm install @itick/chat-react

# Vue 3 封装(可选)
npm install @itick/chat-vue

也可以通过 <script> 标签直接引入 UMD 包:

<script src="https://unpkg.com/@itick/chat-core/dist/chat-core.umd.js"></script>
<script>
  const sdk = new ChatSDK.ChatSDK({ /* ... */ });
</script>

快速接入

原生 JavaScript

import { ChatSDK } from '@itick/chat-core';

const sdk = new ChatSDK({
  apiUrl: 'https://agent.itick.org/agent/token/stream',
  token: 'your-api-token',
  container: document.getElementById('chat-container'),
  width: '100%',
  height: '600px',
});

// 监听事件
sdk.on('message:receive', ({ message }) => {
  console.log('收到消息:', message.content);
});

sdk.on('error', ({ error }) => {
  console.error('请求出错:', error);
});

// 挂载到页面
sdk.mount();

React

import { ChatWidget, type ChatWidgetRef } from '@itick/chat-react';
import { useRef } from 'react';

function App() {
  const chatRef = useRef<ChatWidgetRef>(null);

  return (
    <ChatWidget
      ref={chatRef}
      apiUrl="https://agent.itick.org/agent/token/stream"
      token="your-api-token"
      width="100%"
      height="600px"
      locale="zh-CN"
      onMessageReceive={({ message }) => console.log(message)}
    />
  );
}

Vue 3

<template>
  <ChatWidget
    ref="chatRef"
    :apiUrl="apiUrl"
    :token="token"
    width="100%"
    height="600px"
    locale="zh-CN"
    @messageReceive="onReceive"
  />
</template>

<script setup>
import { ref } from 'vue';
import { ChatWidget } from '@itick/chat-vue';

const chatRef = ref();
const apiUrl = 'https://agent.itick.org/agent/token/stream';
const token = 'your-api-token';

function onReceive({ message }) {
  console.log(message);
}
</script>

核心配置

字段 类型 必填 默认值 描述
apiUrl string 是 - 流式接口地址
token string 是 - 认证 token,通过 HTTP Header token 字段传递
container HTMLElement 是 - 宿主 DOM 节点
width number | string 否 自适应容器 宽度,支持数字(px)或字符串
height number | string 否 自适应容器 高度
themeColor string 否 "#4F46E5" 主题色
theme 'light' | 'dark' | 'auto' 否 "light" 主题模式
customCSS string 否 - 注入自定义 CSS
locale 'zh-CN' | 'zh-TW' | 'en-US' 否 - 界面语言
placeholder string 否 由 i18n 决定 输入框占位文本
mode 'fast' | 'think' 否 "think" 聊天模式
actions ActionsConfig 否 全部显示 操作按钮显隐配置
disclaimer string 否 由 i18n 决定 免责声明文本
welcomeTitle string 否 由 i18n 决定 空状态欢迎标题
welcomeDescription string 否 由 i18n 决定 空状态欢迎描述
presetQuestions string[] 否 6 个金融问题 空状态预设问题
onQuestionClick (q: string) => void 否 - 预设问题点击回调(SDK 已自动发送消息)
onError (error: Error) => void 否 - 错误回调
renderHistoryMessage (msg: ChatMessage) => HTMLElement | string 否 - 历史消息自定义渲染
renderActions (msg: ChatMessage, callbacks: ActionCallbacks) => HTMLElement | undefined 否 - 自定义操作按钮(追加到默认按钮后)

ActionsConfig

字段 类型 默认值 描述
showCopy boolean true 显示复制按钮
showRegenerate boolean true 显示重新生成按钮
showLike boolean true 显示点赞按钮
showShare boolean true 显示分享按钮

API 文档

ChatSDK 实例方法

生命周期

方法 描述
mount() 挂载到容器,创建 ShadowDOM 并渲染 UI。已销毁时抛错
unmount() 移除 ShadowDOM,取消流式请求,保留实例和消息数据
destroy() 彻底销毁实例,清空所有资源和事件监听

消息管理

方法 描述
sendMessage(content: string): Promise<void> 发送消息,自动创建用户和 AI 消息,发起流式请求
clearMessages() 清空所有消息
getMessages(): ChatMessage[] 获取消息列表副本
setHistoryMessages(messages: ChatMessage[]) 设置历史消息列表

配置管理

方法 描述
updateConfig(partial: Partial<ChatConfig>) 动态修改配置,触发 UI 更新
getConfig(): Readonly<ChatConfig> 获取当前配置的只读副本

插件管理

方法 描述
registerPlugin(plugin: MessageRenderPlugin) 注册消息渲染插件
unregisterPlugin(name: string) 注销插件

状态属性

属性 类型 描述
isMounted boolean 是否已挂载
isDestroyed boolean 是否已销毁

事件系统

通过 sdk.on(event, handler) 注册事件监听,sdk.off(event, handler) 移除。

生命周期事件

事件 参数 触发时机
mount 无 mount() 完成后
unmount 无 unmount() 完成后
destroy 无 destroy() 完成后

消息事件

事件 参数 触发时机
message:send { content: string } 用户发送消息时
message:receive { message: ChatMessage } AI 消息流式完成后
message:streaming { message: ChatMessage; chunk: string } 每次收到 content chunk
message:thinking { message: ChatMessage; chunk: string } 每次收到 think chunk
message:done { message: ChatMessage } 流式输出完成(含主动取消)

操作事件

事件 参数 触发时机
actions:copy { messageId, content, message } 点击复制按钮
actions:regenerate { messageId, message } 点击重新生成按钮
actions:like { messageId, content, message } 点击点赞按钮
actions:share { messageId, content, message } 点击分享按钮

其他事件

事件 参数 触发时机
error { error: Error } 流式请求出错时
config:change { config: ChatConfig } updateConfig() 调用后

使用示例

sdk.on('message:streaming', ({ chunk }) => {
  console.log('收到流式片段:', chunk);
});

sdk.on('message:done', ({ message }) => {
  console.log('消息完成:', message.content);
});

sdk.on('actions:copy', ({ content }) => {
  console.log('用户复制了:', content);
});

消息结构

interface ChatMessage {
  id: string;                    // 唯一标识
  role: 'user' | 'assistant' | 'system';
  segments: MessageSegment[];    // think 与 content 按流顺序混合排列
  content: string;               // 所有 content 段拼接(向后兼容)
  timestamp: number;             // 时间戳
  status?: 'sending' | 'streaming' | 'done' | 'error';
  metadata?: Record<string, unknown>;
}

interface MessageSegment {
  type: 'think' | 'content';
  content: string;
  status: 'streaming' | 'done';
}

segments 数组按流式到达顺序存储 think 和 content 块。例如:

[think] → [content] → [think] → [content] → ...

每个 think 模块拥有独立的 streaming/done 状态,完成后自动折叠。

高级功能

主题切换

// 初始化时设置
const sdk = new ChatSDK({ theme: 'auto', /* ... */ });

// 运行时切换
sdk.updateConfig({ theme: 'dark' });

支持三种模式:light(亮色)、dark(暗色)、auto(跟随系统)。

国际化

const sdk = new ChatSDK({ locale: 'zh-CN', /* ... */ });

// 运行时切换
sdk.updateConfig({ locale: 'en-US' });

支持:zh-CN(简体中文)、zh-TW(繁体中文)、en-US(英文)。

自定义 CSS

const sdk = new ChatSDK({
  customCSS: `
    .chat-message-user .chat-message-bubble {
      border-radius: 20px;
    }
  `,
  /* ... */
});

CSS 通过 ShadowDOM 注入,不会影响宿主页面。可通过 CSS 变量覆盖主题色:

--chat-primary: #4F46E5;
--chat-primary-hover: #4338CA;

操作按钮定制

const sdk = new ChatSDK({
  // 隐藏部分按钮
  actions: {
    showLike: false,
    showShare: false,
  },
  // 添加自定义按钮
  renderActions: (message, callbacks) => {
    const btn = document.createElement('button');
    btn.textContent = '收藏';
    btn.addEventListener('click', () => {
      callbacks.onCopy(message.content);
    });
    return btn;
  },
  /* ... */
});

模式切换

用户可在输入框左下角切换极速模式(fast)和智能分析模式(think)。think 模式下会展示 AI 的思考过程。

// 初始化设置
const sdk = new ChatSDK({ mode: 'fast', /* ... */ });

// 运行时切换
sdk.updateConfig({ mode: 'think' });

消息渲染插件

插件可以覆盖默认的 Markdown 渲染行为:

interface MessageRenderPlugin {
  name: string;
  match: (message: ChatMessage) => boolean;
  render: (message: ChatMessage, shadowRoot: ShadowRoot) => HTMLElement;
  update?: (element: HTMLElement, message: ChatMessage) => void;
}
sdk.registerPlugin({
  name: 'code-highlight',
  match: (msg) => msg.content.includes('```'),
  render: (msg) => {
    const el = document.createElement('div');
    el.innerHTML = /* 自定义渲染逻辑 */;
    return el;
  },
  update: (el, msg) => {
    el.innerHTML = /* 流式更新逻辑 */;
  },
});

// 注销插件
sdk.unregisterPlugin('code-highlight');

注意:注册插件会覆盖内置的 Markdown 渲染。插件按注册顺序从后往前匹配,后注册的优先级更高。

历史消息渲染

const sdk = new ChatSDK({
  renderHistoryMessage: (message) => {
    // 返回 HTML 字符串或 HTMLElement
    return `<div class="custom-message">${message.content}</div>`;
  },
  /* ... */
});

预设问题

const sdk = new ChatSDK({
  presetQuestions: [
    '今日美股三大指数行情如何?',
    'BTC/USDT 当前价格和24小时涨跌幅?',
  ],
  onQuestionClick: (question) => {
    console.log('用户点击了问题:', question);
    // SDK 已自动发送消息,此处仅作为通知钩子
  },
  /* ... */
});

框架集成

React

Props

属性 类型 必填 默认值
apiUrl string 是 -
token string 是 -
width number | string 否 "100%"
height number | string 否 "600px"
themeColor string 否 "#4F46E5"
customCSS string 否 -
locale 'zh-CN' | 'zh-TW' | 'en-US' 否 "zh-CN"
placeholder string 否 -
renderHistoryMessage (msg: ChatMessage) => HTMLElement | string 否 -
onMessageSend (payload: { content: string }) => void 否 -
onMessageReceive (payload: { message: ChatMessage }) => void 否 -
onMessageStreaming (payload: { message: ChatMessage; chunk: string }) => void 否 -
onMessageDone (payload: { message: ChatMessage }) => void 否 -
onError (payload: { error: Error }) => void 否 -
onConfigChange (payload: { config: ChatConfig }) => void 否 -

Ref 方法 (ChatWidgetRef)

方法 签名
sendMessage (content: string) => Promise<void>
clearMessages () => void
getMessages () => ChatMessage[]
setHistoryMessages (messages: ChatMessage[]) => void
registerPlugin (plugin: MessageRenderPlugin) => void
unregisterPlugin (name: string) => void
updateConfig (partial: Partial<ChatConfig>) => void
getSDK () => ChatSDK | null

注意:apiUrl、token、width、height 的 prop 变化不会触发热更新,需要重新挂载组件。themeColor、customCSS、locale、placeholder 支持热更新。

Vue 3

Props

与 React 相同(不含回调类 props)。

Events

事件 参数
messageSend { content: string }
messageReceive { message: ChatMessage }
messageStreaming { message: ChatMessage; chunk: string }
messageDone { message: ChatMessage }
error { error: Error }
configChange { config: ChatConfig }

Expose 方法

与 React ChatWidgetRef 完全一致,额外包含 getSDK()。

接口格式

请求格式

SDK 发送 POST 请求到 apiUrl:

Headers:
  Content-Type: application/json
  token: {your-token}
  Accept: text/event-stream

Body:
{
  "input": {
    "messages": [
      { "type": "human", "content": "用户消息内容" }
    ]
  },
  "config": {
    "configurable": {
      "thread_id": "{uuid}",
      "enable_thinking": true
    }
  }
}
  • thread_id 在实例化时自动生成,用于服务端会话保持
  • enable_thinking 根据 mode 配置决定(think 为 true,fast 为 false)
  • 只发送 role === 'user' 的消息

SSE 响应格式

服务端需返回 Content-Type: text/event-stream,每条数据格式:

data: {"type": "think", "content": "思考过程..."}

data: {"type": "content", "content": "回复内容..."}

data: [DONE]
  • type: "think" — 思考过程,SDK 将其渲染为可折叠的 think 模块
  • type: "content" — 正式回复内容,SDK 渲染为 Markdown 气泡
  • [DONE] — 流结束标记

同时兼容 OpenAI 格式(choices[0].delta.content)。

开发调试

# 安装依赖
npm install

# 构建所有包
npm run build

# 代码检查
npm run lint

常见问题

如何自定义样式?

通过 customCSS 配置注入自定义 CSS,或通过 themeColor 设置主题色。所有样式通过 ShadowDOM 隔离,CSS 变量名以 --chat- 为前缀。

如何处理错误?

通过 onError 配置或 error 事件监听:

const sdk = new ChatSDK({
  onError: (error) => { /* 处理错误 */ },
  /* ... */
});

sdk.on('error', ({ error }) => {
  console.error(error);
});

如何取消流式请求?

用户点击发送按钮(流式输出中会变为停止按钮)即可取消。程序化取消可通过 sdk.unmount() 或 sdk.destroy()。

如何保留会话上下文?

thread_id 在实例化时生成,只要不调用 destroy() 重建实例,同一个实例的多次对话会共享 thread_id,服务端可据此保持会话上下文。

虚拟滚动是否影响消息渲染?

不影响。虚拟滚动仅优化 DOM 节点的创建和回收,消息内容通过 segments 和 content 字段完整保留,操作按钮和推荐问题在消息状态变为 done 时自动追加。

About

依托iTick的数据API,面向股票、外汇、指数、贵金属等场景,提供结构化分析与市场研判

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages