Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

57 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Data Analysis Agent

Data Analysis Agent

用自然语言分析数据 —— 一个生产级 LLM Agent 项目

上传 CSV / Excel,用大白话提问,看 AI Agent 实时拆解、计算、出图、写结论。

Next.js TypeScript DeepSeek Live

🌐 Live Demo · 📊 进度看板 · 🚀 部署指南


Data Analysis Agent product showcase

项目定位

不会写 SQL / Python 的业务用户 也能做数据分析。

把 Excel 丢进去,用自然语言提问,Agent 自主决定每一步要调用什么工具(看数据 → 计算 → 出图 → 给结论),全过程实时流式展示,让用户能看到 AI 的每一个动作。

一次完整交互

用户:    哪个区域销售额最高?

Agent:   [Database]    正在读取数据结构...         ✓
         [Calculator]  正在按区域汇总销售额...    ✓
         [BarChart]    正在生成图表...            ✓

         华东区域销售额最高,达 **44,700** 元,
         比第二名华北(31,500)高出 42%。

         [📊 柱状图已渲染]
         [📄 下载 .html 报告]

每一步可见、每一个数字可追溯。导出的 HTML 报告离线可双击打开,内嵌图表 SVG,普通用户友好。


演示

面试现场可以直接照着 docs/demo-script.md 跑一遍:选择内置「销售数据」demo,提问「哪个区域销售额最高?请生成柱状图」,再让 Agent 生成简短报告。

Demo flow: choose dataset, inspect agent steps and charts, export HTML report

数据集即刻可用 Agent 步骤可追溯 报告可离线交付
Dataset sidebar with demo datasets Agent analysis steps and generated chart Generated report card with exportable HTML

一眼能看到的产品闭环

  • 不是 Chat UI 套壳:Agent 会展示 inspect_data → run_analysis → create_chart → generate_report 的完整执行轨迹。
  • 不是编答案:二级 LLM 只负责生成 SQLite SQL,数字由 better-sqlite3:memory: 数据库里真实计算。
  • 不是 demo-only:Prisma/Postgres 持久化、Auth.js 登录、owner check、HTML 报告导出都已经接上。

核心特性

  • 🤖 多步 Agent 推理 — 自动调用 inspect_datarun_analysiscreate_chartgenerate_report
  • 🌊 全程流式 — 文字 / 工具步骤 / 图表 / 报告通过 SSE 实时推送
  • 🧠 支持 DeepSeek V4 thinking modereasoning_content 字段按协议回 echo
  • 🗃️ 真 SQL 执行 — LLM 生成 SQLite SQL → better-sqlite3 :memory: 执行,支持 GROUP BY / 窗口函数 / CTE
  • 💾 Prisma 7 + Postgres 持久化 — driver adapter 架构(@prisma/adapter-pg,无 Rust binary),6 表、5 次 migration 进 git,刷新不丢数据
  • 🔐 生产级鉴权 — Auth.js v5 + bcrypt(12) + JWT;Credentials / Google / GitHub 三 provider;邮箱验证 + 登录失败滑动窗口(15min/5 次)+ enumeration 防御;proxy.ts 路由级保护、owner 校验防越权
  • 📊 4 种图表类型 — bar / line / pie / scatter,基于 Recharts,主题色自动跟随
  • 📄 HTML 报告导出 — 内嵌 SVG 图表,离线可双击打开,无外部依赖
  • 🌗 明 / 暗主题 — 14 个语义化 CSS 变量,组件零硬编码颜色
  • 🔄 每数据集独立历史 — 切换数据集互不污染上下文 + sticky-to-bottom 滚动
  • 🌐 Provider 抽象 — DeepSeek / OpenAI / Claude 通过环境变量切换
  • 🛡️ 三层 SQL 安全 — 只允 SELECT/WITH 开头 + 禁 DDL/DML 关键字 + :memory: per-query
  • 动态提问建议 — LLM 根据 dataset schema 生成自然中文示例问题(替代硬编码模板)
  • ✂️ Token 控制 — tool result 截断 + 滑动窗口(最近 40 条消息),长对话不爆上下文
  • 🎯 一键试用 — 内置 2 个 demo 数据集,新用户零门槛体验
  • 🔁 瞬时失败重试 — 限流 / 5xx / 网络抖动指数退避重试,4xx 参数错立即抛(不浪费 token)
  • 📈 可观测性 — 每轮 Agent 记录 LLM/工具 耗时 + token + 失败率,结构化 [agent-metrics] 日志
  • 二次 LLM 缓存 — 同 (datasetId, intent) 复用生成的 SQL,LRU 100 条
  • 🔎 数据集搜索 + 上传进度条 — 侧栏按名过滤、上传百分比进度 +「解析中」阶段
  • 🧪 测试 + CI — vitest 79 例(解析 / SQL 沙箱 / registry / 缓存 / 重试 / 指标)+ GitHub Actions(tsc + lint + test)

技术栈

选型 理由
框架 Next.js 16 (App Router, Turbopack) 全栈一体,API Route 不用单独搭后端
语言 TypeScript strict 类型在 SSE / tool / LLM 协议间流转,必须 strict
LLM DeepSeek V4 (OpenAI 兼容) 中文好、价格低、支持 Tool Use 与 thinking mode
流式 原生 SSE + ReadableStream 单向流足够;WebSocket 是双向通信,本场景过度设计
持久化 Prisma 7 + Postgres(Supabase 仅作宿主) driver adapter 架构(@prisma/adapter-pg,无 Rust binary);6 表、5 次 migration 进 git;连接配置在 prisma.config.ts
鉴权 Auth.js v5 + bcryptjs + Resend Credentials / Google / GitHub 三 provider + JWT + 邮箱验证 + 登录 rate limit + proxy.ts 路由保护
图表 Recharts React 原生 + SVG 输出(可抓取嵌入报告)
样式 Tailwind v4 + CSS variables @theme inline 让 token 体系天然落地
主题 next-themes SSR 安全、不闪
Markdown react-markdown + remark-gfm 14 个元素 custom map,贴合对话紧凑场景
解析 papaparse + exceljs 服务端解析;exceljs 替代 xlsx 解 CVE
SQL 执行 better-sqlite3 :memory: 替代 node:vm 沙箱;真 SQL 引擎 + 三层防御
报告 marked + inline CSS 离线可读 + 内嵌 SVG 图表

架构核心

Agent 主循环是整个项目的心脏(lib/agent.ts,约 250 行):

sequenceDiagram
    actor U as 用户
    participant FE as React (useAgent)
    participant API as /api/agent (SSE)
    participant Agent as runAgent
    participant LLM as DeepSeek V4
    participant Tool as 工具执行器

    U->>FE: 上传 CSV + 提问
    FE->>API: POST { datasetId, message, previousMessages }
    API->>Agent: runAgent({ ..., onEvent })

    loop step < MAX_STEPS
        Agent->>LLM: chatCompletionStream(messages, tools)
        LLM-->>Agent: chunks (content / reasoning / tool_calls)
        Agent-->>FE: SSE answer_delta (流式文本)

        alt 有 tool_calls
            Agent-->>FE: SSE tool_start
            Agent->>Tool: execute (inspect / analysis / chart / report)
            Tool-->>FE: SSE chart / report (via ctx.emit)
            Tool-->>Agent: result JSON
            Agent-->>FE: SSE tool_done
        else 无 tool_calls (结束)
            Agent-->>FE: SSE done (本轮新增 messages)
        end
    end
Loading

快速开始

环境要求

本地启动

git clone https://github.com/vaezc/data-analysis-agent.git
cd data-analysis-agent
npm install

# 配置环境变量(分两个文件)
cp .env.local.example .env.local
# .env 放数据库连接(Prisma CLI 只认 .env)
cat > .env <<EOF
DATABASE_URL="postgresql://...:6543/postgres?pgbouncer=true&connection_limit=1"
DIRECT_URL="postgresql://...:5432/postgres"
EOF
# .env.local 放 LLM key、AUTH_SECRET 等
# 生成 AUTH_SECRET: openssl rand -base64 32

# 初始化数据库表结构
npx prisma migrate deploy   # 生产/CI 用 deploy;本地开发用 prisma migrate dev

# 启动
npm run dev

浏览器打开 http://localhost:3000

试一下

  1. 上传 scripts/sample.csv(项目自带的小销售数据)
  2. 输入 "哪个区域销售额最高?"
  3. 看 Agent 一步步推理

部署到 Vercel

# 1. push 到自己的 GitHub 仓库
# 2. Vercel 导入项目
# 3. 添加环境变量(Production scope):
#    LLM_PROVIDER          = deepseek
#    LLM_API_KEY           = sk-xxx
#    LLM_MODEL             = deepseek-v4-flash
#    DATABASE_URL          = postgresql://...:6543/postgres?pgbouncer=true&connection_limit=1
#    DIRECT_URL            = postgresql://...:5432/postgres
#    AUTH_SECRET           = <openssl rand -base64 32>
#    AUTH_URL              = https://<your-domain>.vercel.app
#    AUTH_TRUST_HOST       = true   # Vercel preview / 自定义域名必加
# 4. Deploy(build = "prisma generate && next build",构建不连库)
#    注:migration 不在 build 里跑。新增 migration 时部署前先手动
#    npm run db:migrate:deploy(详见 DEPLOY.md §4)

项目结构

data-analysis-agent/
├── app/
│   ├── api/
│   │   ├── agent/route.ts                # SSE Agent 端点
│   │   ├── upload/route.ts               # 文件上传 + 解析
│   │   ├── datasets/
│   │   │   ├── route.ts                  # GET 列表
│   │   │   └── [id]/
│   │   │       ├── route.ts              # DELETE
│   │   │       └── suggestions/route.ts  # GET LLM 生成的提问建议
│   │   └── messages/route.ts             # GET 历史 / DELETE 清空
│   ├── page.tsx                          # 主对话界面 + sidebar
│   └── globals.css                       # 14 个语义 CSS token
├── lib/
│   ├── agent.ts                          # ★ Agent 主循环
│   ├── llm.ts                            # Provider 抽象
│   ├── prisma.ts                         # Prisma client 单例(HMR-safe)
│   ├── db/
│   │   ├── datasets.ts                   # 数据集 CRUD + owner check
│   │   └── messages.ts                   # 对话持久化 + 滑动窗口 + 配对删除
│   ├── auth/
│   │   ├── email.ts                      # Resend 邮箱验证发送
│   │   └── rate-limit.ts                 # 登录失败 rate limit
│   ├── suggestions.ts                    # LLM 生成自然中文提问建议
│   └── tools/
│       ├── registry.ts                   # ★ 自注册中心:defineTool + executeTool + getToolList
│       ├── index.ts                      # 副作用 import 触发各工具自注册 + re-export
│       ├── inspect-data.ts               # 工具 1:schema + handler + UI 描述同文件
│       ├── run-analysis.ts               # 工具 2:含 uiDescriptionFrom 动态文案 + 截断
│       ├── create-chart.ts               # 工具 3:zod superRefine 兜 pie / 长度校验
│       ├── generate-report.ts            # 工具 4
│       └── sqlite-runner.ts              # ★ better-sqlite3 SQL 沙箱
├── prisma/
│   ├── schema.prisma                     # 6 表 schema
│   └── migrations/                       # 5 次 migration 进 git
├── auth.ts                               # Auth.js v5 完整配置
├── auth.config.ts                        # edge-safe 部分(给 proxy.ts 用)
├── proxy.ts                              # Next.js 16 路由保护(旧名 middleware.ts)
├── hooks/
│   └── use-agent.ts                      # SSE 消费 + per-dataset 历史
├── components/chat/
│   ├── ChatPanel.tsx                     # 输入区 + sticky-to-bottom 滚动
│   ├── MessageBubble.tsx
│   ├── ChartRenderer.tsx
│   ├── ReportCard.tsx                    # HTML 导出 + 内嵌 SVG
│   └── StepList.tsx
└── types/index.ts                        # 全局类型(StreamEvent / ChatMessage)

推荐阅读路径

想了解什么 看哪里
Agent 主循环 + 三种 delta 累积 lib/agent.ts
SSE 流式协议 + UTF-8 安全 hooks/use-agent.ts
工具自注册 registry(借鉴 Hermes Agent) lib/tools/registry.ts
Tool result 截断(控 token) lib/tools/run-analysis.ts
HTML 报告内嵌 SVG 图表 components/chat/ReportCard.tsx
Sticky-to-bottom 滚动 components/chat/ChatPanel.tsx
Prisma 数据访问层 + owner check lib/db/datasets.ts · lib/db/messages.ts

文档导览

  • PROGRESS.md — 项目蓝图 + 局限登记册 + 优化项 backlog
  • DEPLOY.md — Vercel 端到端部署 checklist(13 项环境变量)
  • CLAUDE.md — 开发规范与约束

Roadmap

  • Phase 1 — Agent 主循环、工具系统、SSE 流式
  • Phase 2 — Recharts 图表、明暗主题、流式 answer、多轮上下文
  • Phase 3 — HTML 报告 + Supabase 持久化 + Vercel 上线
  • 安全 / 性能 polish
    • xlsx → exceljs(解 CVE)
    • node:vm → better-sqlite3 真 SQL 执行(解 vm 不安全 + 不支持 async)
    • 滑动窗口 + tool result 截断(控 LLM token)
  • UX polish
    • 错误条 dismiss、数据集删除、New Chat、HistorySkeleton
    • Demo 数据集 + 一键试用按钮
    • LLM 生成的动态提问建议
  • Vision 多模态架构 — 后端协议层 ready,前端 UI 待 vision-capable LLM 启用
  • 工具系统重构 — 自注册 registry(借鉴 Nous Research Hermes Agent)+ zod 校验,新增工具只需 1 个文件
  • 鉴权完整化 — 登录失败 rate limit(DB 滑动窗口)+ 邮箱验证(Resend + 24h TTL)+ OAuth(Google / GitHub)
  • Prisma 6 → 7 升级 — WASM driver adapter,包体积 14MB → 1.6MB,cold start 加速
  • E2B 沙箱 — 替代 better-sqlite3 跑真 Python(需付费 API key)
  • 二次 LLM 调用缓存 — 同 intent 复用,省 token
  • 多 Excel sheet 支持 — 当前只读第一个
  • 可观测性 — 耗时、token、失败率监控

完整登记见 PROGRESS.md


License

MIT


Built with Claude Code.

Releases

Packages

Contributors

Languages