273 lines
7.5 KiB
Markdown
273 lines
7.5 KiB
Markdown
# aichat
|
|
|
|
一个基于 Go + Gin 的 AI 聊天 Web 应用,默认使用火山引擎 Ark/OpenAI 兼容接口,支持多模型配置、流式输出、工具调用、图片输入、上下文窗口管理和本地对话历史。
|
|
|
|
## 功能特性
|
|
|
|
- **多模型配置**:在配置文件中维护多个 OpenAI 兼容模型,并可在页面中切换当前模型。
|
|
- **流式对话**:通过 SSE 实时返回模型响应,支持 Token 统计与速度展示。
|
|
- **工具调用**:内置搜索、计算器、时间、SQL 查询等工具,并通过工具路由按需调用。
|
|
- **上下文窗口管理**:根据模型上下文长度自动保留、截断历史消息。
|
|
- **对话持久化**:会话保存在本地 `conversations/` 目录,支持创建、查看和删除。
|
|
- **多模态输入**:支持图片消息输入,由兼容多模态的模型处理。
|
|
- **思考标签解析**:可解析模型输出中的 `<think>` 内容并单独展示。
|
|
|
|
## 技术栈
|
|
|
|
- Go 1.25+
|
|
- Gin Web Framework
|
|
- 火山引擎 Ark SDK / OpenAI 兼容接口
|
|
- YAML 配置
|
|
- SQLite / MySQL 驱动
|
|
- 原生 HTML/CSS/JavaScript
|
|
|
|
## 快速开始
|
|
|
|
### 1. 克隆项目
|
|
|
|
```bash
|
|
git clone <your-repo-url>
|
|
cd aichat
|
|
```
|
|
|
|
### 2. 安装依赖
|
|
|
|
```bash
|
|
go mod download
|
|
```
|
|
|
|
### 3. 准备配置
|
|
|
|
首次运行时,程序会自动生成 `config.yaml`。你也可以手动创建:
|
|
|
|
```yaml
|
|
server:
|
|
mode: tcp
|
|
address: 0.0.0.0:8080
|
|
|
|
openai:
|
|
- name: doubao
|
|
active: true
|
|
api_key: ${ARK_API_KEY}
|
|
base_url: https://ark.cn-beijing.volces.com/api/v3
|
|
model: doubao-seed-2-0-pro-260215
|
|
timeout: 120
|
|
context_window_tokens: 262144
|
|
|
|
tool_router:
|
|
enabled: true
|
|
openai_name: doubao
|
|
timeout: 30
|
|
max_tokens: 512
|
|
system_prompt: |-
|
|
你可以按需直接调用可用工具来回答用户问题。
|
|
每个工具的 description 描述了它的适用场景和调用条件。
|
|
工具结果优先于模型内置知识;工具失败时必须如实说明,不要编造结果。
|
|
只调用确实必要的工具。
|
|
```
|
|
|
|
建议使用环境变量提供密钥,避免把 API Key 写入仓库:
|
|
|
|
```bash
|
|
export ARK_API_KEY="your-ark-api-key"
|
|
```
|
|
|
|
> `config.yaml` 已在 `.gitignore` 中忽略,适合作为本地私有配置文件。
|
|
|
|
### 4. 启动服务
|
|
|
|
```bash
|
|
go run main.go
|
|
```
|
|
|
|
启动后访问:
|
|
|
|
```text
|
|
http://localhost:8080
|
|
```
|
|
|
|
## 构建与测试
|
|
|
|
```bash
|
|
# 构建二进制
|
|
go build -o aichat main.go
|
|
|
|
# 运行全部测试
|
|
go test ./...
|
|
|
|
# 查看详细测试输出
|
|
go test -v ./...
|
|
```
|
|
|
|
## 配置说明
|
|
|
|
### `server`
|
|
|
|
| 字段 | 说明 | 示例 |
|
|
| --- | --- | --- |
|
|
| `mode` | 服务监听模式,支持 `tcp` 或 Unix socket | `tcp` |
|
|
| `address` | 监听地址 | `0.0.0.0:8080` |
|
|
|
|
### `openai`
|
|
|
|
`openai` 是模型配置列表,也兼容单对象配置。常用字段:
|
|
|
|
| 字段 | 说明 |
|
|
| --- | --- |
|
|
| `name` | 配置名称,用于页面展示和切换 |
|
|
| `active` | 是否为默认激活模型;多个配置只能有一个激活 |
|
|
| `api_key` | API Key;也可用 `ARK_API_KEY` 环境变量覆盖 |
|
|
| `base_url` | OpenAI 兼容接口地址 |
|
|
| `model` | 模型名称 |
|
|
| `timeout` | 请求超时时间,单位秒 |
|
|
| `context_window_tokens` | 上下文窗口 Token 上限 |
|
|
| `parse_think_tags` | 是否解析 `<think>` 标签,可选 |
|
|
|
|
### `tool_router`
|
|
|
|
工具路由用于判断用户问题是否需要调用工具。
|
|
|
|
| 字段 | 说明 |
|
|
| --- | --- |
|
|
| `enabled` | 是否启用工具路由 |
|
|
| `openai_name` | 用于工具路由决策的模型配置名称,留空时使用当前激活模型 |
|
|
| `timeout` | 工具路由请求超时时间,单位秒 |
|
|
| `max_tokens` | 工具路由最大输出 Token 数 |
|
|
| `system_prompt` | 工具路由系统提示词 |
|
|
| `tools` | 可选的工具覆盖配置 |
|
|
|
|
## 内置工具
|
|
|
|
工具配置位于 `agents/*/config.yaml`。
|
|
|
|
| 工具 | 默认状态 | 说明 |
|
|
| --- | --- | --- |
|
|
| `search` | 启用 | 联网搜索,默认 DuckDuckGo,可用于实时信息、新闻、版本、网页核验等场景 |
|
|
| `calculator` | 启用 | 四则运算和简单数学表达式计算 |
|
|
| `time` | 启用 | 将“今天、明天、本周”等相对时间转换为绝对日期范围 |
|
|
| `sql` | 禁用 | 查询本地业务数据库,默认 SQLite 只读连接 |
|
|
|
|
### 搜索工具
|
|
|
|
默认配置:
|
|
|
|
```yaml
|
|
enabled: true
|
|
profiles:
|
|
- name: duckduckgo
|
|
active: true
|
|
enabled: true
|
|
provider: duckduckgo
|
|
base_url: https://api.duckduckgo.com/
|
|
count: 5
|
|
timeout: 10
|
|
```
|
|
|
|
如果使用 Brave Search,可设置:
|
|
|
|
```bash
|
|
export BRAVE_SEARCH_API_KEY="your-brave-search-api-key"
|
|
```
|
|
|
|
### SQL 工具
|
|
|
|
SQL 工具默认关闭。开启前请确认数据库连接、权限和表白名单配置:
|
|
|
|
```yaml
|
|
enabled: true
|
|
default_database: default
|
|
databases:
|
|
- name: default
|
|
active: true
|
|
driver: sqlite
|
|
dsn: file:data/app.db?mode=ro
|
|
timeout: 10
|
|
max_rows: 50
|
|
max_cell_bytes: 4096
|
|
schema:
|
|
include_tables: []
|
|
exclude_tables: []
|
|
```
|
|
|
|
## HTTP API
|
|
|
|
| 方法 | 路径 | 说明 |
|
|
| --- | --- | --- |
|
|
| `GET` | `/` | Web 聊天页面 |
|
|
| `POST` | `/api/chat` | 流式聊天接口 |
|
|
| `GET` | `/api/openai` | 获取模型配置列表 |
|
|
| `POST` | `/api/openai/active` | 切换当前激活模型 |
|
|
| `GET` | `/api/search` | 获取搜索配置列表 |
|
|
| `POST` | `/api/search/active` | 切换当前激活搜索源 |
|
|
| `GET` | `/api/conversations` | 获取对话列表 |
|
|
| `POST` | `/api/conversations` | 创建新对话 |
|
|
| `GET` | `/api/conversations/:id` | 获取指定对话 |
|
|
| `DELETE` | `/api/conversations/:id` | 删除指定对话 |
|
|
|
|
## 项目结构
|
|
|
|
```text
|
|
.
|
|
├── main.go # 应用入口
|
|
├── config.yaml # 本地配置文件(已忽略)
|
|
├── config/ # 配置加载、默认值和规范化
|
|
├── server/ # HTTP 服务、路由和处理器
|
|
├── llm/ # LLM 客户端与模型状态管理
|
|
├── message/ # 消息结构和格式转换
|
|
├── stream/ # SSE、流式响应、Token 统计
|
|
├── contextwindow/ # 上下文窗口管理
|
|
├── conversation/ # 对话历史存储
|
|
├── agenttool/ # 工具注册与加载框架
|
|
├── toolmanager/ # 工具管理器
|
|
├── toolrouter/ # 工具路由和调用循环
|
|
├── agents/ # 内置工具实现与配置
|
|
│ ├── search/
|
|
│ ├── calculator/
|
|
│ ├── time/
|
|
│ └── sql/
|
|
└── templates/ # 前端页面模板
|
|
```
|
|
|
|
## 添加新工具
|
|
|
|
1. 在 `agents/<tool-name>/` 下新增工具实现和 `config.yaml`。
|
|
2. 在工具配置中提供 `enabled` 和 `activation_prompt`,说明工具适用场景。
|
|
3. 使用 `agenttool` 注册工具,确保工具管理器能加载到该工具。
|
|
4. 根据需要补充测试用例。
|
|
5. 运行:
|
|
|
|
```bash
|
|
go test ./...
|
|
```
|
|
|
|
## 常见问题
|
|
|
|
### 配置文件不存在怎么办?
|
|
|
|
程序启动时会自动创建默认 `config.yaml`。你只需要补充模型名称和 API Key。
|
|
|
|
### 如何避免提交密钥?
|
|
|
|
`config.yaml` 已被 `.gitignore` 忽略。推荐使用环境变量:
|
|
|
|
```bash
|
|
export ARK_API_KEY="your-ark-api-key"
|
|
```
|
|
|
|
### 为什么工具没有被调用?
|
|
|
|
请检查:
|
|
|
|
1. `tool_router.enabled` 是否为 `true`。
|
|
2. 对应 `agents/<tool>/config.yaml` 中 `enabled` 是否为 `true`。
|
|
3. 用户问题是否符合该工具的 `activation_prompt`。
|
|
4. 工具路由模型配置 `tool_router.openai_name` 是否存在且可用。
|
|
|
|
### 对话记录保存在哪里?
|
|
|
|
默认保存在本地 `conversations/` 目录。该目录已被 `.gitignore` 忽略。
|
|
|
|
## License
|
|
|
|
请根据项目实际情况补充许可证信息。
|