# Koishi Plugin: DeepSeek API Chat

[![npm version](https://img.shields.io/npm/v/koishi-plugin-deepseekapi-chat)](https://www.npmjs.com/package/koishi-plugin-deepseekapi-chat)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

高性能 DeepSeek 大模型接入插件，支持自定义系统人设、多轮对话记忆、详细参数调节，提供 .ds/.ai 指令和智能直聊模式，适合群聊智能助手。

## 功能特性

### 🚀 核心功能
- **DeepSeek API 集成**：无缝接入 DeepSeek 官方 API，支持最新模型
- **多轮对话记忆**：可配置的上下文轮数，保持对话连贯性
- **自定义人设系统**：灵活的系统提示词配置，打造专属 AI 角色
- **智能参数调节**：温度、top_p、惩罚系数等完整参数控制

### 💬 交互模式
- **命令模式**：使用 `.ds` 或 `.ai` 指令进行对话
- **智能直聊模式**：
  - 私聊自动响应（无需指令前缀）
  - 群聊 @机器人 响应
  - 可配置触发前缀
- **对话管理**：支持 `.ds -r` 清空当前会话记忆

### ⚙️ 高级特性
- **上下文隔离**：支持群聊独立上下文或个人共享上下文
- **人设强调机制**：可配置系统提示词注入频率
- **专业日志系统**：使用 Koishi 专用日志实例，支持结构化日志输出
- **错误处理**：友好的错误提示和重试机制
- **状态监控**：管理员可查看插件运行状态

## 安装方法

### 在 Koishi 控制台安装
1. 进入 Koishi 控制台
2. 转到「插件市场」
3. 搜索「deepseekapi-chat」
4. 点击安装

### 手动安装
```bash
# 通过 npm
npm install koishi-plugin-deepseekapi-chat

# 或通过 yarn
yarn add koishi-plugin-deepseekapi-chat
```

## 配置说明

### 必需配置
```yaml
# 在 Koishi 配置文件中添加
plugins:
  deepseekapi-chat:
    apiKey: 'your-deepseek-api-key-here'  # DeepSeek API 密钥
```

### 完整配置选项

#### API 设置
| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| `apiKey` | `string` | `''` | **必需** DeepSeek API 密钥 |
| `endpoint` | `string` | `'https://api.deepseek.com'` | API 接入点 URL |
| `model` | `string` | `'deepseek-chat'` | 使用的模型名称 |

#### 人设与提示词
| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| `systemPrompt` | `string` | `'你是一个 helpful 的 AI 助手...'` | 系统提示词，用于设定 AI 的角色和行为 |
| `injectSystemPromptEveryTime` | `boolean` | `false` | 是否每次请求都重新注入 System Prompt |
| `injectSystemPromptInterval` | `number` | `5` | 人设强调频率：每隔 X 轮对话注入一次 System Prompt |

#### 对话上下文管理
| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| `maxContextRounds` | `number` | `10` | 最大保留的对话轮数（0 = 不保留历史） |
| `separateGroupContext` | `boolean` | `true` | 每个群聊是否使用独立的上下文 |

#### 生成参数
| 配置项 | 类型 | 默认值 | 范围 | 说明 |
|--------|------|--------|------|------|
| `temperature` | `number` | `0.7` | `0-2` | 创造性，越高越随机 |
| `top_p` | `number` | `0.9` | `0-1` | 核采样概率 |
| `max_tokens` | `number` | `1024` | `1-4096` | 最大生成令牌数 |
| `frequency_penalty` | `number` | `0` | `-2~2` | 频率惩罚，降低重复度 |
| `presence_penalty` | `number` | `0` | `-2~2` | 存在惩罚，鼓励新话题 |

#### 行为控制
| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| `stream` | `boolean` | `false` | 是否启用流式输出（未来扩展） |
| `verboseApiLog` | `boolean` | `false` | 是否打印详细的 API 日志 |
| `verboseError` | `boolean` | `false` | 是否显示详细的错误信息 |
| `formatMessageWithUser` | `boolean` | `false` | 是否在 AI 回复前添加用户标识 |

#### 直聊模式配置
| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| `enableDirectChatInPrivate` | `boolean` | `true` | 是否在私聊中启用直聊模式 |
| `enableDirectChatOnAt` | `boolean` | `true` | 是否在群聊中启用 @ 直聊模式 |
| `directChatPrefix` | `string` | `''` | 直聊模式触发前缀（如空则无前缀） |
| `bypassDirectChatPrefixInPrivate` | `boolean` | `false` | 在私聊中是否忽略过滤词前缀。开启后，即使设置了过滤词，在私聊中也能直接触发机器人 |

## 使用方法

### 命令模式
```
.ds <问题>          # 向 DeepSeek 提问
.ai <问题>          # 别名，功能相同
.ds -r              # 清空当前会话记忆
.deepseek-status    # 查看插件状态（仅管理员）
```

**示例：**
```
用户：.ds 什么是人工智能？
AI：人工智能是...

用户：.ds 用 Python 写一个冒泡排序
AI：```python
def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        for j in range(0, n-i-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
    return arr
```

### 直聊模式

#### 私聊直聊
1. 默认已启用（`enableDirectChatInPrivate: true`）
2. 在私聊中直接发送消息即可获得响应
3. 如需禁用，可设置 `enableDirectChatInPrivate: false`

#### 群聊 @ 直聊
1. 默认已启用（`enableDirectChatOnAt: true`）
2. 在群聊中 @机器人 并发送消息
3. 如需禁用，可设置 `enableDirectChatOnAt: false`

**示例：**
```
用户：@机器人 今天天气怎么样？
AI：今天天气晴朗，气温 25°C...
```

### 前缀直聊与过滤词
配置 `directChatPrefix` 可设置触发前缀：
```yaml
directChatPrefix: '!ai'
```
使用方式：`!ai 今天天气怎么样？`

**私聊忽略前缀功能**：
当设置了 `directChatPrefix` 过滤词时，私聊默认需要匹配前缀才能触发。如需在私聊中忽略前缀检查，可启用 `bypassDirectChatPrefixInPrivate: true`。

## 实现原理

### 架构设计
```
用户输入 → 中间件/命令处理器 → 会话管理器 → API 调用 → 响应处理 → 用户输出
```

### 核心组件

#### 1. 会话管理
- 使用 `Map` 数据结构存储会话历史
- 会话 ID 生成规则：
  - 群聊独立上下文：`group:{groupId}:user:{userId}`
  - 群聊共享上下文：`group:{groupId}`
  - 私聊：`user:{userId}`
- 自动清理超出 `maxContextRounds` 的历史消息

#### 2. 消息处理流程
```javascript
1. 接收用户输入
2. 获取或创建会话历史
3. 条件性注入 System Prompt（根据配置频率）
4. 构建 API 请求消息体
5. 调用 DeepSeek API
6. 处理响应并更新会话历史
7. 返回 AI 回复
```

#### 3. 上下文管理策略
- **轮数计算**：仅计算用户和 AI 的对话轮数，系统提示不计入
- **人设强调**：可配置每隔 N 轮重新注入系统提示词，保持 AI "人设"
- **历史裁剪**：FIFO 原则，保留最近的对话

#### 4. API 集成
- 使用 `fetch` 进行 HTTP 请求
- 完整的错误处理（401、429 等状态码）
- 支持流式输出（未来扩展）

### 性能优化
- **内存效率**：仅保留必要的历史消息
- **网络优化**：合理的超时和重试机制
- **日志控制**：可配置的详细日志，避免生产环境噪音

## 注意事项

### API 密钥安全
1. 不要在代码中硬编码 API 密钥
2. 使用环境变量或 Koishi 配置管理
3. 定期轮换 API 密钥

### 使用限制
1. DeepSeek API 有调用频率限制
2. 上下文长度受 `max_tokens` 限制
3. 长时间对话可能产生较高费用

### 最佳实践
1. **人设设计**：精心设计 `systemPrompt` 以获得更好的对话效果
2. **上下文轮数**：根据使用场景调整 `maxContextRounds`（建议 5-15）
3. **温度设置**：创意场景用较高温度（0.8-1.2），严谨场景用较低温度（0.3-0.7）
4. **错误处理**：启用 `verboseError` 进行调试，生产环境可关闭

### 常见问题

#### Q: 为什么 AI 回复不一致？
A: 检查 `temperature` 设置，过高会导致随机性增加。

#### Q: 如何清空某个用户的对话历史？
A: 使用 `.ds -r` 命令清空当前会话。

#### Q: API 返回 401 错误？
A: 检查 API 密钥是否正确，是否已过期。

#### Q: 如何查看当前活跃会话？
A: 管理员使用 `.deepseek-status` 命令。

## 更新日志

### v1.3.0 (最新版本)
- **新增功能**：添加 `bypassDirectChatPrefixInPrivate` 配置项，支持在私聊中忽略过滤词前缀
- **默认值优化**：直聊模式默认启用（`enableDirectChatInPrivate` 和 `enableDirectChatOnAt` 默认值改为 `true`）
- **日志系统升级**：使用 Koishi 专用日志实例，提供更结构化的日志输出
- **配置描述改进**：多个配置项的描述更加详细和准确

### v1.2.2
- 优化了上下文管理逻辑
- 修复了会话轮数计算问题
- 增强了错误提示信息

### v1.2.0
- 新增直聊模式（私聊和 @ 响应）
- 添加系统提示词间隔注入功能
- 改进配置项描述

### v1.1.0
- 支持多轮对话记忆
- 添加详细的生成参数配置
- 优化 API 错误处理

### v1.0.0
- 初始版本发布
- 基础 DeepSeek API 集成
- 命令模式支持

## 开发指南

### 本地开发
```bash
# 克隆仓库
git clone <repository-url>

# 安装依赖
cd koishi-plugin-deepseekapi-chat
npm install

# 开发测试
npm run dev
```

### 代码结构
```
src/
├── index.js          # 插件主文件
└── (未来扩展)
```

### 贡献指南
1. Fork 本仓库
2. 创建功能分支
3. 提交更改
4. 发起 Pull Request

## 许可证

本项目采用 MIT 许可证。详见 [LICENSE](LICENSE) 文件。

## 支持与反馈

如有问题或建议，请：
1. 查看 [GitHub Issues](https://github.com/your-repo/issues)
2. 提交新的 Issue
3. 或通过其他联系方式反馈

---

**温馨提示**：合理使用 AI 技术，遵守相关法律法规和平台规定。