Skip to content

cultist123/gomini

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Gomini — AI 聊天应用

一个基于 React + Spring Boot 的全栈 AI 聊天应用,支持 SSE 流式输出、多轮对话管理、用户认证与对话持久化。

项目概览

┌─────────────────────────────────────────────────────┐
│                    前端 (React 19)                   │
│  TypeScript · Vite 8 · Axios · Fetch SSE 流式解析    │
│                                                     │
│  ┌─────────┐ ┌──────────┐ ┌───────────┐            │
│  │ Sidebar  │ │ ChatView │ │ LoginForm │            │
│  │ 对话列表  │ │ 消息列表  │ │ 登录/注册  │            │
│  └─────────┘ └──────────┘ └───────────┘            │
└──────────────────────┬──────────────────────────────┘
                       │  REST + SSE (port 8080)
┌──────────────────────┴──────────────────────────────┐
│                 后端 (Spring Boot 2.7)               │
│  Java 11 · Spring Data JPA · JWT · SseEmitter       │
│                                                     │
│  ┌──────────────┐ ┌────────────────┐                │
│  │ ClaudeService │ │ Conversation   │                │
│  │ 流式 AI 转发  │ │ Service 持久化  │                │
│  └──────┬───────┘ └───────┬────────┘                │
└─────────┼─────────────────┼─────────────────────────┘
          │                 │
    Claude API (SSE)    PostgreSQL
   (兼容 OpenAI 格式)   (对话持久化)

技术栈

前端

技术 版本 说明
React 19.2 UI 框架
TypeScript 5.9 类型安全
Vite 8.0 构建工具 (Oxc 编译)
Axios 1.14 REST API 调用
Fetch API SSE 流式接收 (POST + ReadableStream)

后端

技术 版本 说明
Spring Boot 2.7.18 Web 框架
Java 11 运行环境
Spring Data JPA ORM + PostgreSQL 持久化
Spring Security Crypto BCrypt 密码加密
JJWT 0.11.5 JWT Token 签发/验证
Java HttpClient HTTP/2 流式转发 Claude API
Maven 构建管理

数据库

技术 说明
PostgreSQL 用户、对话、消息持久化存储

功能特性

用户系统

  • 注册(用户名 + 密码 + 手机号 + 邮箱,密码要求 8 位以上含大小写和数字)
  • 登录(JWT Token,24 小时有效期)
  • BCrypt 密码加密
  • 用户名/邮箱/手机号唯一性校验

AI 对话

  • SSE 流式输出,前端逐字显示 + 光标动画
  • 多轮对话上下文(内存缓存,最大 50 条消息,30 分钟 TTL 自动清理)
  • AI 自动生成对话标题
  • 可配置模型(默认 glm-5,兼容 OpenAI Messages API 格式)

对话管理

  • 创建/切换/删除对话
  • 对话持久化到 PostgreSQL
  • 侧边栏历史列表(中文相对时间:刚刚/x分钟前/x小时前/x天前)
  • 新建对话时自动保存

UI 交互

  • 可折叠侧边栏
  • 右上角头像按钮弹出登录/用户面板(点击外部关闭)
  • AI 思考中三点弹跳动画
  • 消息气泡自动滚动
  • 输入框自适应高度,Enter 发送 / Shift+Enter 换行

项目结构

gomini/
├── frontend/                           # 前端项目
│   ├── src/
│   │   ├── main.tsx                    # React 入口
│   │   ├── App.tsx                     # 根组件(全部状态管理 + API 调用)
│   │   ├── App.css                     # 布局样式
│   │   ├── index.css                   # CSS 变量 + 全局重置
│   │   └── components/
│   │       ├── LoginForm.tsx/css        # 登录/注册表单(双模式切换)
│   │       ├── ChatView.tsx/css         # 聊天消息列表(自动滚动)
│   │       ├── ChatInput.tsx/css        # 消息输入框(自适应高度)
│   │       ├── MessageBubble.tsx/css    # 消息气泡(user/assistant 样式)
│   │       ├── Sidebar.tsx/css          # 侧边栏(对话历史 + 新建/删除)
│   │       ├── UserPanel.tsx/css        # 用户信息面板
│   │       ├── AvatarButton.tsx/css     # 头像按钮(弹出登录或面板)
│   │       └── TypingIndicator.tsx/css  # AI 思考中动画
│   ├── public/
│   │   ├── favicon.svg                 # 站点图标
│   │   └── icons.svg                   # 图标精灵
│   ├── package.json
│   ├── vite.config.ts
│   ├── tsconfig.json / tsconfig.app.json / tsconfig.node.json
│   └── eslint.config.js
│
├── backend/                            # 后端项目
│   ├── src/main/java/com/example/backend/
│   │   ├── BackendApplication.java     # Spring Boot 入口
│   │   ├── config/
│   │   │   ├── ClaudeConfig.java       # Claude API RestTemplate 配置
│   │   │   └── WebConfig.java          # CORS + AuthInterceptor 注册
│   │   ├── controller/
│   │   │   ├── ChatController.java     # POST /api/chat (SSE 流式)
│   │   │   ├── ConversationController.java  # 对话 CRUD
│   │   │   ├── LoginController.java    # POST /api/login, /api/register
│   │   │   └── TitleController.java    # POST /api/title (AI 生成标题)
│   │   ├── service/
│   │   │   ├── ClaudeService.java      # Claude API 流式/非流式调用 + 内存会话缓存
│   │   │   ├── ConversationService.java # 对话持久化业务逻辑
│   │   │   ├── TitleService.java       # AI 标题生成(调用 Claude API)
│   │   │   └── UserService.java        # 注册/登录 + BCrypt 加密
│   │   ├── entity/
│   │   │   ├── User.java               # 用户表 (users)
│   │   │   ├── Conversation.java       # 对话表 (conversations)
│   │   │   └── ConversationMessage.java # 消息表 (conversation_messages)
│   │   ├── repository/
│   │   │   ├── UserRepository.java
│   │   │   └── ConversationRepository.java
│   │   ├── interceptor/
│   │   │   └── AuthInterceptor.java    # JWT 认证拦截器
│   │   ├── dto/                        # 请求/响应数据传输对象
│   │   │   ├── auth/                   # LoginRequest, RegisterRequest
│   │   │   ├── chat/                   # ChatRequest, StreamEvent, ClaudeApiResponse...
│   │   │   ├── conversation/           # 对话相关 DTO
│   │   │   ├── common/                 # ApiResponse<T> 统一响应
│   │   │   └── user/                   # UserDto
│   │   ├── exception/                  # 全局异常处理
│   │   └── util/
│   │       └── JwtUtil.java            # JWT 签发/解析/验证
│   ├── src/main/resources/
│   │   └── application.properties      # 数据库 + Claude API + JWT 配置
│   ├── pom.xml                         # Maven 依赖
│   └── mvnw / mvnw.cmd                # Maven Wrapper
│
└── .gitignore

数据库设计

users                           conversations                    conversation_messages
┌──────────────────┐           ┌──────────────────────┐         ┌─────────────────────┐
│ id (PK, BIGSERIAL)│          │ id (PK, BIGSERIAL)    │         │ id (PK, BIGSERIAL)   │
│ username (50, UQ) │──┐       │ user_id (FK→users)    │         │ conversation_id      │
│ phone (20, UQ)    │  │       │ title (100)           │ 1    N  │  (FK→conversations)  │
│ country_code (10) │  │       │ created_at            │────────▶│ role (20)            │
│ email (100, UQ)   │  └──────▶│ updated_at            │         │ content (TEXT)       │
│ password_hash     │          └──────────────────────┘         │ created_at           │
│ created_at        │                                           └─────────────────────┘
└──────────────────┘
  • users.username / users.phone / users.email 均有唯一约束
  • conversationsupdated_at 降序排列
  • conversation_messagescreated_at 升序排列
  • JPA ddl-auto=update,启动时自动建表

API 接口

认证(无需 Token)

方法 路径 说明 请求体
POST /api/register 注册 { username, password, phone, countryCode, email }
POST /api/login 登录 { username, password } → 返回 { token, userInfo }

对话管理(需 Authorization: Bearer {token}

方法 路径 说明
GET /api/conversations 获取当前用户的对话列表
GET /api/conversations/:id 获取对话详情(含全部消息)
POST /api/conversations 创建新对话 { title?, messages[] }
PUT /api/conversations/:id 更新对话(追加消息) { title?, newMessages[] }
DELETE /api/conversations/:id 删除对话

AI 聊天(无需 Token,SSE 流式)

方法 路径 说明
POST /api/chat 发送消息,流式返回 AI 回复
POST /api/title 根据对话内容生成标题

/api/chat 请求与 SSE 响应

请求体:

{
  "conversationId": "可选,为空则创建新会话",
  "model": "glm-5",
  "maxTokens": 1024,
  "messages": [{ "role": "user", "content": "你好" }]
}

SSE 事件流(text/event-stream):

type data 说明
connected "连接已建立" SSE 连接就绪
text_delta "文本片段" AI 回复逐字推送
message_complete { conversationId, model, stopReason, inputTokens, outputTokens } 回复完成
error "错误信息" 异常

快速开始

环境要求

  • 前端: Node.js 18+, npm
  • 后端: Java 11+, Maven 3.6+(或使用 Maven Wrapper)
  • 数据库: PostgreSQL 12+

1. 启动数据库

# 方式一:本地 PostgreSQL
createdb postgres    # 如尚未创建
# 默认连接:localhost:5432, 用户 postgres, 密码 root

# 方式二:Docker
docker run -d --name gomini-postgres \
  -e POSTGRES_PASSWORD=root \
  -e POSTGRES_USER=postgres \
  -e POSTGRES_DB=postgres \
  -p 5432:5432 postgres:latest

2. 启动后端

cd backend

# 修改数据库配置(如需要)
# 编辑 src/main/resources/application.properties

# 配置 Claude API(必须)
# claude.base-url=<你的 API 地址>
# claude.auth-token=<你的 Token>

# 启动
./mvnw spring-boot:run          # Linux/Mac
mvnw.cmd spring-boot:run        # Windows

后端运行在 http://localhost:8080,JPA 会自动建表。

3. 启动前端

cd frontend
npm install
npm run dev

前端运行在 http://localhost:5173,API 请求发往 http://localhost:8080

4. 构建生产版本

cd frontend
npm run build    # 输出到 dist/
npm run preview  # 预览生产构建

配置说明

后端 application.properties

# 数据库
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=root

# Claude API(兼容 OpenAI Messages API 格式)
claude.base-url=http://your-api-server/api    # API 基础地址
claude.auth-token=your_token                  # 认证 Token
claude.model=glm-5                            # 默认模型
claude.max-tokens=1024                        # 最大输出 token
claude.conversation-ttl-minutes=30            # 内存会话缓存 TTL

# JWT
jwt.secret=YourSuperSecretKey...              # 签名密钥(≥256 bit)

前端

API 地址硬编码在 frontend/src/App.tsx 中:

const API_BASE = 'http://localhost:8080'

生产环境部署时修改此值或通过 Vite 环境变量配置。

核心流程

聊天流式流程

用户输入消息
    │
    ▼
POST /api/chat (JSON body)
    │
    ▼
ClaudeService.chatStream()
    │  ├─ 生成 conversationId(新会话)
    │  ├─ 加载内存会话历史(最多 50 条)
    │  └─ 拼装请求 → Claude API (stream=true)
    │
    ▼
SseEmitter 逐行解析上游 SSE
    │
    ├─ content_block_delta → 转发 text_delta 给前端
    ├─ message_stop       → 发送 message_complete + 保存历史
    └─ error              → 转发错误信息
    │
    ▼
前端逐字渲染 + 保存对话到后端
    │
    ▼
ConversationService 持久化到 PostgreSQL

认证流程

注册: POST /api/register → BCrypt 加密密码 → 存入 users 表
登录: POST /api/login → BCrypt 验证 → JJWT 签发 Token(24h)
请求: Authorization: Bearer <token> → AuthInterceptor 解析 → 按 username 查 userId
过期: 前端收到 401/403 → 清除 localStorage → 弹出登录框

About

一个支持JWT用户认证、SSE流式输出和多对话历史管理的全栈AI聊天应用(Gomini)。

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors