ChatBI
用自然语言探索股票数据,把查询、分析与可视化连接在一次对话里。
查看源码
项目概述
ChatBI 股票查询助手是一个 AI-Native 对话式商业智能(ChatBI)股票分析系统。用户可以通过自然语言对话的方式查询 A 股行情数据,系统利用大语言模型(LLM)自动完成意图识别、SQL 生成、数据查询、图表渲染和 ARIMA 趋势预测等全流程操作。同时配备了一套完整的管理后台,支持用户管理、操作审计、会话管理、AI 模型配置和 Prompt 模板管理。
核心能力:
- 自然语言查询:用户输入自然语言问题(如"贵州茅台最近 30 天涨跌幅"),系统自动转换为 SQL 查询并返回结果
- 智能数据分析:LLM 对查询结果进行趋势分析、对比分析、极值查询、统计分析等多维度专业解读
- ARIMA 趋势预测:基于时间序列模型预测股票未来走势,附带 95% 置信区间
- 数据可视化:自动渲染折线图、柱状图和预测图表
- 向量语义检索:通过 Chroma 向量数据库实现 Schema 和 SQL 示例的语义相似度检索,提升 SQL 生成准确率
- 查询缓存:基于问题文本哈希的查询结果缓存机制,避免重复计算
- 多轮上下文对话:支持带上下文的连续对话,最多保留 10 轮历史
- 管理后台:用户管理、会话管理、操作审计、查询审计、登录日志、AI 模型配置、Prompt 模板管理
数据范围:当前覆盖贵州茅台(600519.SH)、五粮液(000858.SZ)、中芯国际(688981.SH)、广发证券(000776.SZ)四支股票的日线行情数据。
技术选型
后端
| 技术 | 版本 | 用途 |
|---|---|---|
| Python | 3.12+ | 主要编程语言 |
| FastAPI | 0.110+ | Web 框架,提供 REST API + SSE 流式接口 |
| Pydantic Settings | 2.0+ | 配置管理(.env 环境变量) |
| SQLite | - | 本地数据存储(股票数据 + 业务表 + 向量库) |
| JWT + bcrypt | - | 认证鉴权与密码加密 |
| OpenAI SDK | 1.0+ | LLM 调用客户端(兼容 DashScope 接口) |
| LangChain | 0.2+ | LLM 缓存、Chroma 向量检索 |
| LangGraph | 0.2+ | 工作流编排(PipelineState 状态图) |
| ChromaDB | 0.5+ | 向量数据库(Schema 字段 + SQL 示例的 Embedding 存储) |
| pandas | 2.0+ | 数据处理与 Excel 导出 |
| matplotlib | 3.8+ | 图表渲染(折线图/柱状图/ARIMA 预测图) |
| statsmodels | 0.14+ | ARIMA 时间序列预测 |
| Tushare | 1.4+ | A 股日线行情数据源 |
前端
| 技术 | 版本 | 用途 |
|---|---|---|
| React | 19 | 前端框架 |
| TypeScript | 6.0 | 类型安全 |
| Vite | 8.0 | 构建工具与开发服务器 |
| Ant Design | 6.3 | UI 组件库 |
| Zustand | 5.0 | 轻量级状态管理 |
| Axios | 1.15 | HTTP 请求 |
| React Router | 7 | 前端路由 |
| ECharts | 6.0 | 前端图表渲染 |
| react-markdown | 10.1 | Markdown 内容渲染 |
| highlight.js + KaTeX | - | 代码高亮与数学公式渲染 |
| streamdown | 2.5 | 流式 Markdown 渲染 |
外部服务
| 服务 | 用途 |
|---|---|
| DashScope(阿里云灵积) | LLM 调用(deepseek-v4-pro 模型)+ Embedding(text-embedding-v3) |
| Tushare | A 股日线行情数据获取 |
实现过程
1. 系统架构
┌─────────────────────────────────────────────────────┐
│ 前端 (React) │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ 聊天页面 │ │ 管理后台 │ │ Zustand 状态管理 │ │
│ └─────┬─────┘ └────┬─────┘ └──────────────────┘ │
│ │ │ │
│ │ SSE 流式 │ REST API │
└────────┼──────────────┼─────────────────────────────┘
│ │
v v
┌─────────────────────────────────────────────────────┐
│ 后端 (FastAPI) │
│ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ 认证路由 │ │ 管理路由 │ │ 聊天路由/SSE 路由 │ │
│ └────┬─────┘ └────┬─────┘ └────────┬─────────┘ │
│ │ │ │ │
│ ┌────┴─────┐ ┌─────┴──────┐ ┌──────┴──────────┐ │
│ │ 认证服务 │ │ 管理服务 │ │ 聊天编排服务 │ │
│ │ │ │ (886行) │ │ (1277行) │ │
│ └─────────┘ └────────────┘ └──────┬──────────┘ │
│ │ │
│ ┌────────────┼────────────┐ │
│ v v v │
│ ┌──────────┐ ┌────────┐ ┌──────────┐
│ │语义层 │ │SQL引擎 │ │ARIMA预测 │
│ │(749行) │ │ │ │ │
│ └──────────┘ └────────┘ └──────────┘
└─────────────────────────────────────────────────────┘
│ │ │
v v v
┌─────────────────────────────────────────────────────┐
│ 数据层 │
│ ┌────────────┐ ┌────────────┐ ┌───────────────┐ │
│ │stock_prices│ │schema_ │ │ Chroma │ │
│ │.db (行情) │ │vector.db │ │ 向量数据库 │ │
│ │ │ │(语义元数据) │ │ (Embedding) │ │
│ └────────────┘ └────────────┘ └───────────────┘ │
└─────────────────────────────────────────────────────┘
2. 自然语言查询流程
这是系统的核心业务流程,从用户输入自然语言到返回分析结果,经历以下阶段:
用户输入自然语言问题
│
v
┌───────────────────┐
│ ① 意图归一化 │ 整合会话上下文,判断问题类型
│ │ - forecast: 预测请求
│ │ - query: 数据查询
│ │ - chat: 闲聊
└───────┬───────────┘
│
├── forecast ──> [ARIMA 预测流程] ──> 图表 + 文字总结
├── chat ──────> [LLM 闲聊回复]
│
└── query ────> 数据查询主流程
│
v
┌───────────────────┐
│ ② 语义层扩展 │ 同义词映射(如"茅台"→"贵州茅台")
│ │ "收盘价"→"close"、"涨跌幅"→"pct_chg"
└───────┬───────────┘
│
v
┌───────────────────┐
│ ③ 向量语义检索 │ 检索相关 Schema 字段和 SQL 示例
│ │ - Chroma 向量数据库 (LangChain 集成)
│ │ - SQLite 内建向量 (余弦相似度计算)
└───────┬───────────┘
│
v
┌───────────────────┐
│ ④ 查询缓存检查 │ SHA256(问题文本) 作为缓存键
│ │ 命中 → 直接返回历史结果
│ │ 未命中 → 继续流程
└───────┬───────────┘
│
v
┌───────────────────┐
│ ⑤ LLM 生成 SQL │ Prompt 包含:
│ │ - 表 DDL(CREATE TABLE 语句)
│ │ - 股票代码映射表
│ │ - 语义层扩展后的用户问题
│ │ - 向量检索到的相关 Schema 字段
│ │ - 向量检索到的相似 SQL 示例
└───────┬───────────┘
│
v
┌───────────────────┐
│ ⑥ SQL 安全校验 │ 禁止 INSERT/UPDATE/DELETE/DROP
│ │ 限制返回行数 (MAX_RESULT_ROWS)
│ │ 查询超时控制 (QUERY_TIMEOUT_SECONDS)
└───────┬───────────┘
│
v
┌───────────────────┐
│ ⑦ SQL 执行 │ SQLite 引擎执行
│ (失败则LLM纠错) │ 失败 → LLM 纠错重试(最多3次)
└───────┬───────────┘
│
v
┌───────────────────┐
│ ⑧ 图表渲染 │ matplotlib 生成 PNG 图表
│ │ 自动选择折线图或柱状图
└───────┬───────────┘
│
v
┌───────────────────┐
│ ⑨ LLM 数据分析 │ 5 种分析模式:
│ │ - trend: 趋势分析
│ │ - compare: 对比分析
│ │ - extreme: 极值查询
│ │ - statistics: 统计分析
│ │ - evaluate: 综合评价
└───────┬───────────┘
│
v
┌───────────────────┐
│ ⑩ 结果缓存 + 返回 │ 缓存结果 (TTL 默认 600 秒)
│ │ 通过 SSE 流式输出或同步返回
└───────────────────┘
2.1 语义层设计
语义层是整个系统 SQL 生成准确率的核心保障,位于 semantic_layer.py(约 749 行),包含以下模块:
- Schema 元数据表(
schema_metadata):存储 12 个字段的详细业务语义描述,包括字段名、类型、业务含义、是否为关键字段等 - 语义同义词表(
semantic_layer):存储股票名称、指标、维度的同义词映射。例如用户说"茅台",系统会自动扩展为"贵州茅台";用户说"涨跌幅",系统映射到数据库字段pct_chg - SQL 示例库(
sql_examples):9 个预置的 question-SQL 配对,包括查询、排序、聚合、分组等典型场景,用于 Few-shot 提示 - 向量表(
schema_vectors):将 Schema 字段语义描述和 SQL 示例通过 Embedding API 转换为向量,存储在 SQLite 和 Chroma 中,支持语义相似度检索
2.2 向量检索方案
系统实现了 双重向量检索 机制:
- Chroma 向量数据库(通过 LangChain 集成):在应用启动时自动从 SQLite 种子数据初始化 Chroma 集合,创建
schema_fields和sql_examples两个集合 - SQLite 内建向量(自定义余弦相似度):作为 Chroma 不可用时的回退方案,或作为补充检索
2.3 查询缓存
为了提高响应速度并降低 LLM 调用成本,系统实现了查询缓存机制:
- 缓存键:
SHA256(归一化后的问题文本 + SQL) - 缓存存储:SQLite 的
query_cache表 - 默认 TTL:600 秒(可通过
QUERY_CACHE_TTL环境变量配置) - 缓存命中时直接返回之前的结果、图表和分析总结,无需重新执行全流程
3. ARIMA 趋势预测
系统使用 statsmodels 库实现 ARIMA(5,1,5) 时间序列预测,位于 backend/services/arima_stock.py。
实现步骤:
- 数据准备:从 SQLite 提取目标股票的历史收盘价序列(按日期升序排列)
- 差分处理:对序列进行一阶差分(
d=1),使数据平稳化 - 模型拟合:使用 ARIMA(5,1,5) 对历史数据建模(自回归阶数 p=5,差分阶数 d=1,移动平均阶数 q=5)
- 未来预测:预测未来 N 个交易日的收盘价,附带 95% 置信区间(上下界)
- 图表渲染:使用 matplotlib 生成包含历史数据、预测值、置信区间的可视化图表
- 自然语言触发:用户通过自然语言触发预测(如"预测贵州茅台未来 30 天走势"),意图归一化自动识别为 forecast 类型
4. 流式输出(SSE)
系统使用 Server-Sent Events(SSE)实现聊天过程中的实时流式输出,位于 backend/routers/chat_stream.py 和 frontend/src/hooks/useSSE.ts。
SSE 事件类型:
| 事件类型 | 说明 |
|---|---|
intent |
意图识别结果(forecast/query/chat) |
tokens |
LLM 生成的 token 流 |
sql_chunk |
SQL 语句片段(逐步展示) |
data_info |
数据查询完成通知(返回行数、耗时) |
chart |
图表生成完成(返回图片 URL) |
analysis_tokens |
数据分析 token 流 |
done |
整个流程完成 |
error |
错误信息 |
前端使用 streamdown 库实现流式 Markdown 渲染,使用 react-markdown + rehype-highlight + rehype-katex 实现代码高亮和数学公式渲染。
5. 管理后台
管理后台提供了完整的运维能力,后端 API 位于 backend/routers/admin.py(16 个接口),业务逻辑位于 backend/services/admin_service.py(约 886 行),前端页面位于 frontend/src/pages/Admin/。
管理功能模块:
| 模块 | 功能 |
|---|---|
| 面板总览 | 今日登录数、用户数、活跃用户数、会话数、失败登录数 |
| 用户管理 | 用户 CRUD、角色分配(superadmin/admin/user)、状态管理、密码重置 |
| 会话管理 | 查看/删除/置顶所有用户的聊天会话,查看完整消息历史 |
| 操作审计 | 管理员操作日志(创建用户、修改角色、删除会话等) |
| 查询审计 | 所有用户的自然语言查询记录,包含 SQL、耗时、缓存命中、图表生成状态,支持导出 Excel |
| 登录日志 | 所有用户的登录成功/失败记录,含 IP 和 User-Agent |
| AI 模型配置 | 动态修改模型名称、Base URL、超时、重试次数、上下文轮数 |
| Prompt 模板管理 | 动态编辑 SQL 生成规则、分析师系统提示词、Few-shot 示例 |
6. 前端架构
前端采用 React 19 + TypeScript + Vite 构建,目录结构如下:
frontend/src/
├── components/ # UI 组件
│ ├── ChatMessageBox/ # 聊天消息气泡组件
│ ├── DataTable/ # 数据表格组件
│ ├── Sidebar/ # 侧边栏(会话列表)
│ ├── SqlBlock/ # SQL 代码块展示组件
│ └── ThemeToggle/ # 主题切换组件
├── hooks/ # 自定义 Hook
│ └── useSSE.ts # SSE 流式消费 Hook
├── layouts/ # 布局组件
│ └── ChatLayout/ # 聊天页面布局
├── pages/ # 页面
│ ├── Chat/ # 聊天页面
│ ├── Admin/ # 管理后台页面
│ └── Login/ # 登录页面
├── services/ # Axios API 封装
│ ├── admin.ts
│ ├── auth.ts
│ ├── chat.ts
│ └── session.ts
├── stores/ # Zustand 状态管理
│ ├── auth.ts # 认证状态
│ ├── chat.ts # 聊天状态
│ └── ui.ts # UI 状态(主题、侧边栏等)
└── types/ # TypeScript 类型定义
状态管理:使用 Zustand 实现轻量级全局状态管理,分为三个 Store:
authStore:用户认证信息、登录状态chatStore:当前会话、消息列表、流式状态uiStore:主题模式、侧边栏折叠状态
流式聊天:useSSE Hook 封装了 SSE 连接的生命周期管理,包括连接建立、事件监听、重连机制和连接清理。
7. 安全设计
- 认证鉴权:JWT Token + bcrypt 密码加密,支持角色权限(superadmin/admin/user)
- SQL 安全:禁止 INSERT/UPDATE/DELETE/DROP/ALTER/CREATE 等写操作语句,仅允许 SELECT
- 查询限制:结果行数上限(默认 5000 行)、查询超时(默认 60 秒)
- SQL 纠错:执行失败时自动调用 LLM 进行纠错重试,最多 3 次,避免因 LLM 生成的不完美 SQL 导致查询失败
8. 配置管理
系统使用 Pydantic Settings 进行配置管理,所有配置项通过 .env 文件或环境变量注入,位于 backend/config.py。
核心配置项:
| 配置项 | 默认值 | 说明 |
|---|---|---|
MODEL_NAME |
deepseek-v4-pro |
LLM 模型名称 |
DASHSCOPE_BASE_URL |
https://dashscope.aliyuncs.com/compatible-mode/v1 |
LLM API 地址 |
TUSHARE_TOKEN |
- | Tushare 数据源 Token |
MAX_RETRY |
3 | SQL 纠错最大重试次数 |
MAX_CONTEXT_ROUNDS |
5 | 上下文最大轮数 |
QUERY_CACHE_TTL |
600 | 查询缓存过期时间(秒) |
MAX_RESULT_ROWS |
5000 | 查询结果最大行数 |
QUERY_TIMEOUT_SECONDS |
60 | 查询超时时间(秒) |
目录结构
ChatBI助手/
├── backend/ # FastAPI 后端
│ ├── main.py # 应用入口,路由注册与初始化
│ ├── config.py # 配置中心 (Pydantic Settings)
│ ├── llm.py # LLM Embedding 配置
│ ├── memory.py # LangChain 记忆模块
│ ├── schemas.py # 公共 Pydantic 模型
│ ├── callbacks.py # LLM 回调处理
│ ├── vector_store.py # Chroma 向量存储操作
│ ├── engine/ # SQL 执行引擎
│ │ ├── base.py # 引擎抽象基类
│ │ └── sqlite_engine.py # SQLite 引擎实现
│ ├── graph/ # LangGraph 工作流
│ │ ├── nodes.py # 工作流节点定义
│ │ └── state.py # 状态定义
│ ├── models/ # API 请求/响应模型
│ │ ├── admin.py
│ │ ├── auth.py
│ │ ├── chat.py
│ │ └── common.py
│ ├── prompts/ # LLM 提示词模板
│ │ ├── analyst.py # 数据分析师提示词
│ │ ├── classify.py # 意图分类提示词
│ │ ├── common.py # 通用提示词常量
│ │ ├── correction.py # SQL 纠错提示词
│ │ └── sql_generator.py # SQL 生成提示词
│ ├── routers/ # API 路由层
│ │ ├── admin.py # 管理后台接口 (16个)
│ │ ├── auth.py # 认证接口
│ │ ├── chat.py # 同步聊天接口
│ │ ├── chat_stream.py # SSE 流式聊天接口
│ │ └── session.py # 会话管理接口
│ └── services/ # 业务逻辑层
│ ├── chat_service.py # 核心:意图识别+SQL生成+执行+分析 (1277行)
│ ├── arima_stock.py # ARIMA 时间序列预测
│ ├── admin_service.py # 管理后台服务 (886行)
│ ├── auth_service.py # 认证鉴权服务
│ ├── session_service.py # 会话管理服务
│ └── security.py # SQL 安全校验
├── frontend/ # React + Vite 前端
│ └── src/
│ ├── App.tsx # 前端入口(路由、权限守卫、主题配置)
│ ├── main.tsx # React 渲染入口
│ ├── index.css # 全局样式
│ ├── components/ # UI 组件
│ ├── hooks/ # 自定义 Hook (useSSE)
│ ├── layouts/ # 布局组件
│ ├── pages/ # 页面组件
│ ├── services/ # Axios API 封装
│ ├── stores/ # Zustand 状态管理
│ └── types/ # TypeScript 类型定义
├── semantic_layer.py # 语义层元数据、向量检索、缓存 (749行)
├── logger_utils.py # 日志工具
├── prepare_stock_data.py # 股票数据生成脚本
├── stock_prices.sql # 股票价格表结构定义
├── requirements.txt # Python 依赖清单
├── .env.example # 环境变量模板
├── LICENSE # MIT 许可证
└── README.md # 项目说明