http://localhost:3000application/jsonPOST /auth/register
Content-Type: application/json
{
"username": "string",
"password": "string"
}
响应:
{
"message": "用户创建成功",
"user": {
"id": "string",
"username": "string",
"isAdmin": false
}
}
POST /auth/login
Content-Type: application/json
{
"username": "string",
"password": "string"
}
响应:
{
"access_token": "jwt_token_string",
"user": {
"id": "string",
"username": "string",
"isAdmin": false
}
}
POST /auth/change-password
Authorization: Bearer <token>
Content-Type: application/json
{
"currentPassword": "string",
"newPassword": "string"
}
GET /model-configs
Authorization: Bearer <token>
响应:
[
{
"id": "string",
"name": "string",
"provider": "openai|gemini",
"modelId": "string",
"baseUrl": "string",
"type": "llm|embedding|rerank",
"supportsVision": boolean
}
]
POST /model-configs
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "string",
"provider": "openai|gemini",
"modelId": "string",
"baseUrl": "string",
"apiKey": "string",
"type": "llm|embedding|rerank",
"supportsVision": boolean
}
PUT /model-configs/:id
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "string",
"apiKey": "string",
// ... 其他字段
}
DELETE /model-configs/:id
Authorization: Bearer <token>
POST /upload
Authorization: Bearer <token>
Content-Type: multipart/form-data
{
"file": File,
"chunkSize": number,
"chunkOverlap": number,
"embeddingModelId": "string",
"mode": "fast|precise" // 处理模式
}
响应:
{
"id": "string",
"name": "string",
"originalName": "string",
"size": number,
"mimetype": "string",
"status": "pending|indexing|completed|failed"
}
GET /knowledge-bases
Authorization: Bearer <token>
响应:
[
{
"id": "string",
"name": "string",
"originalName": "string",
"size": number,
"mimetype": "string",
"status": "pending|indexing|completed|failed",
"createdAt": "datetime"
}
]
DELETE /knowledge-bases/:id
Authorization: Bearer <token>
DELETE /knowledge-bases/clear
Authorization: Bearer <token>
POST /chat/stream
Authorization: Bearer <token>
Content-Type: application/json
{
"message": "string",
"history": [
{
"role": "user|assistant",
"content": "string"
}
],
"userLanguage": "zh|en|ja"
}
响应: Server-Sent Events (SSE)
data: {"type": "content", "data": "正在搜索知识库..."}
data: {"type": "content", "data": "找到相关信息..."}
data: {"type": "content", "data": "回答内容片段"}
data: {"type": "sources", "data": [
{
"fileName": "string",
"content": "string",
"score": number,
"chunkIndex": number
}
]}
data: [DONE]
GET /user-settings
Authorization: Bearer <token>
响应:
{
"selectedLLMId": "string",
"selectedEmbeddingId": "string",
"selectedRerankId": "string",
"temperature": number,
"maxTokens": number,
"topK": number,
"enableRerank": boolean,
"similarityThreshold": number,
"enableFullTextSearch": boolean,
"language": "zh|en|ja"
}
PUT /user-settings
Authorization: Bearer <token>
Content-Type: application/json
{
"selectedLLMId": "string",
"temperature": number,
"maxTokens": number,
// ... 其他设置字段
}
GET /api/vision/recommend-mode?file=xxx&size=xxx
Authorization: Bearer <token>
响应:
{
"recommendedMode": "precise",
"reason": "由于文件较大,推荐使用高精度模式",
"estimatedCost": 0.5,
"estimatedTime": 60,
"warnings": ["处理时间可能会较长", "会产生API使用费用"]
}
POST /libreoffice/convert
Content-Type: multipart/form-data
{
"file": File
}
响应:
{
"pdf_path": "/uploads/document.pdf",
"converted": true,
"original": "document.docx",
"file_size": 102400
}
GET /libreoffice/health
响应:
{
"status": "healthy",
"service": "libreoffice-converter",
"version": "1.0.0",
"uptime": 3600.5
}
GET /users
Authorization: Bearer <admin_token>
POST /users
Authorization: Bearer <admin_token>
Content-Type: application/json
{
"username": "string",
"password": "string",
"isAdmin": boolean
}
DELETE /users/:id
Authorization: Bearer <admin_token>
{
"statusCode": number,
"message": "string",
"error": "string"
}
200 - 成功201 - 创建成功400 - 请求参数无效401 - 认证错误 / 令牌无效403 - 权限不足404 - 资源未找到409 - 资源冲突500 - 服务器内部错误// 登录
const loginResponse = await fetch('/auth/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username: 'user',
password: 'password'
})
});
const { access_token } = await loginResponse.json();
// 获取文件列表
const filesResponse = await fetch('/knowledge-bases', {
headers: {
'Authorization': `Bearer ${access_token}`
}
});
const files = await filesResponse.json();
// 流式聊天
const chatResponse = await fetch('/chat/stream', {
method: 'POST',
headers: {
'Authorization': `Bearer ${access_token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
message: '你好',
history: [],
userLanguage: 'ja'
})
});
const reader = chatResponse.body.getReader();
// SSE 流的处理...
本项目已实现完整的开放API功能,支持外部系统通过API Key进行认证和访问。
ApiController)| 端点 | 方法 | 描述 | 认证方式 |
|---|---|---|---|
/health |
GET | 健康检查 | 无 |
/chat |
POST | 简单聊天接口 | JWT |
ApiV1Controller)| 端点 | 方法 | 描述 | 认证方式 |
|---|---|---|---|
/api/v1/chat |
POST | RAG聊天(支持流式SSE和JSON响应) | API Key |
/api/v1/search |
POST | 知识库混合搜索 | API Key |
/api/v1/knowledge-bases |
GET | 列出知识库文件 | API Key |
/api/v1/knowledge-bases/upload |
POST | 上传文件到知识库 | API Key |
/api/v1/knowledge-bases/:id |
DELETE | 删除知识库文件 | API Key |
/api/v1/knowledge-bases/:id |
GET | 获取单个文件详情 | API Key |
文件位置: server/src/auth/api-key.guard.ts
支持两种方式传递API Key:
Authorization: Bearer kb_xxx 头x-api-key 头API Key格式: kb_ + 64位十六进制字符串
文件位置: server/src/auth/entities/api-key.entity.ts
@Entity('api_keys')
export class ApiKey {
id: string; // UUID主键
userId: string; // 关联用户ID
key: string; // API Key值(唯一)
createdAt: Date; // 创建时间
}
文件位置: server/src/user/user.service.ts
| 方法 | 描述 |
|---|---|
findByApiKey(apiKey) |
通过API Key查找用户 |
getOrCreateApiKey(userId) |
获取或创建用户的API Key |
regenerateApiKey(userId) |
重新生成API Key |
文件位置: web/src/pages/auth/Login.tsx
支持两种登录方式:
文件位置: web/services/apiClient.ts
x-api-keyx-tenant-id)文件位置: web/src/contexts/AuthContext.tsx
localStorage| 特性 | 状态 | 说明 |
|---|---|---|
| API Key认证 | ✅ 已实现 | 支持Bearer Token和x-api-key两种方式 |
| 多租户隔离 | ✅ 已实现 | 每个API Key关联到特定用户和租户 |
| RAG聊天(流式) | ✅ 已实现 | 支持SSE流式响应 |
| 知识库搜索 | ✅ 已实现 | 支持向量搜索和全文搜索的混合搜索 |
| 文件上传/管理 | ✅ 已实现 | 支持文件上传、列表查询和删除 |
| 前端API Key登录 | ✅ 已实现 | 支持直接使用API Key登录 |
// 使用x-api-key头
const response = await fetch('/api/v1/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'kb_your_api_key_here'
},
body: JSON.stringify({
message: '你好',
stream: false
})
});
// 或使用Authorization头
const response = await fetch('/api/v1/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer kb_your_api_key_here'
},
body: JSON.stringify({
message: '你好',
stream: true
})
});
const formData = new FormData();
formData.append('file', fileInput.files[0]);
formData.append('mode', 'fast');
formData.append('chunkSize', '1000');
formData.append('chunkOverlap', '200');
const response = await fetch('/api/v1/knowledge-bases/upload', {
method: 'POST',
headers: {
'x-api-key': 'kb_your_api_key_here'
},
body: formData
});
| 功能 | 状态 | 说明 |
|---|---|---|
| API Key管理界面 | ❌ 未实现 | 需要在设置页面提供API Key的查看/复制/重新生成功能 |
| API文档页面 | ❌ 未实现 | 需要独立的API文档页面 |
| 细粒度权限控制 | ❌ 未实现 | 目前所有API Key权限相同 |
| API使用统计 | ❌ 未实现 | 需要记录和展示API调用次数和频率 |
| API速率限制 | ❌ 未实现 | 需要防止API滥用 |
server/src/api/api.controller.ts - 基础API控制器server/src/api/api-v1.controller.ts - V1版本开放API控制器server/src/api/api.service.ts - API服务server/src/api/api.module.ts - API模块server/src/auth/api-key.guard.ts - API Key认证守卫server/src/auth/entities/api-key.entity.ts - API Key实体server/src/user/user.service.ts - 用户服务(包含API Key管理)web/src/pages/auth/Login.tsx - 登录页面(支持API Key登录)web/src/contexts/AuthContext.tsx - 认证上下文web/services/apiClient.ts - API客户端