# aichat 一个基于 Go + Gin 的 AI 聊天 Web 应用,默认使用火山引擎 Ark/OpenAI 兼容接口,支持多模型配置、流式输出、工具调用、图片输入、上下文窗口管理和本地对话历史。 ## 功能特性 - **多模型配置**:在配置文件中维护多个 OpenAI 兼容模型,并可在页面中切换当前模型。 - **流式对话**:通过 SSE 实时返回模型响应,支持 Token 统计与速度展示。 - **工具调用**:内置搜索、计算器、时间、SQL 查询等工具,并通过工具路由按需调用。 - **上下文窗口管理**:根据模型上下文长度自动保留、截断历史消息。 - **对话持久化**:会话保存在本地 `conversations/` 目录,支持创建、查看和删除。 - **多模态输入**:支持图片消息输入,由兼容多模态的模型处理。 - **思考标签解析**:可解析模型输出中的 `` 内容并单独展示。 ## 技术栈 - Go 1.25+ - Gin Web Framework - 火山引擎 Ark SDK / OpenAI 兼容接口 - YAML 配置 - SQLite / MySQL 驱动 - 原生 HTML/CSS/JavaScript ## 快速开始 ### 1. 克隆项目 ```bash git clone 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` | 是否解析 `` 标签,可选 | ### `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//` 下新增工具实现和 `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//config.yaml` 中 `enabled` 是否为 `true`。 3. 用户问题是否符合该工具的 `activation_prompt`。 4. 工具路由模型配置 `tool_router.openai_name` 是否存在且可用。 ### 对话记录保存在哪里? 默认保存在本地 `conversations/` 目录。该目录已被 `.gitignore` 忽略。 ## License 请根据项目实际情况补充许可证信息。