内容
# <img src="https://raw.githubusercontent.com/xsip/liquid-local-ai-client/refs/heads/main/apps/ui/public/logo-cropped.png" alt="Logo" width="30"/> Liquid Local AI Client | [Preview on youtube](https://www.youtube.com/watch?v=_UhKke10JzY)
一个完整的全栈AI聊天客户端,通过标准的`/v1/chat/completions`端点连接到任何与OpenAI兼容的本地推理服务器(LM Studio、Ollama、llama.cpp、vLLM、...)。使用Angular、NestJS和MongoDB构建,支持一流的MCP(Model Context Protocol)工具、通过[InvokeAI](https://invoke-ai.github.io/InvokeAI/)进行AI图像生成、聊天中的图像上传和可选的端到端AES消息加密。
> **⚠️ Breaking change:** LM Studio的原生`/api/v1/chat` API和与OpenAI兼容的`/v1/responses/create`(Responses API)端点已**禁用**。有关详细信息和替代方案,请参见下面的[Chat Completions API(当前默认)](#chat-completions-api-current-default)。
---

---
## 目录
- [概述](#overview)
- [Chat Completions API(当前默认)](#chat-completions-api-current-default)
- [架构](#architecture)
- [功能](#features)
- [技术栈](#tech-stack)
- [项目结构](#project-structure)
- [前提条件](#prerequisites)
- [环境变量](#environment-variables)
- [快速入门](#getting-started)
- [MCP工具集成](#mcp-tool-integration)
- [图像生成(InvokeAI)](#image-generation-invokeai)
- [图像上传](#image-upload)
- [消息加密](#message-encryption)
- [身份验证和授权](#authentication--authorization)
- [令牌使用和速率限制](#token-usage--rate-limiting)
- [API概述](#api-overview)
---
## 概述
该monorepo包含两个应用程序:
| 应用 | 位置 | 描述 |
| --- | --- | --- |
| `api` | `apps/api` | NestJS REST后端、MCP服务器和LM Studio代理 |
| `ui` | `apps/ui` | Angular 21单页聊天界面 |
后端作为身份验证代理,连接Angular前端和本地推理服务器。所有聊天会话都存储在MongoDB中,每个用户的令牌使用情况都被跟踪。后端运行自己的**MCP客户端**,按需调用工具,而不是依赖推理服务器自己协调工具调用。MCP工具集包括图像生成工具,通过InvokeAI连接本地实例,上传的图像存储在MongoDB中作为二进制大对象,并通过API返回。
---
## Chat Completions API(当前默认)
LM Studio最近禁用了连接到本地MCP服务器,这破坏了该项目的原始架构:Responses API (`/v1/responses/create`)通过给予LM Studio一个指向后端MCP服务器的`type: 'mcp'`工具来工作,并依赖LM Studio本身连接、列出工具、调用它们,并将结果反馈给模型。随着每个请求的本地MCP连接被禁用,这种流程不再可行。
解决方法是完全停止依赖推理服务器进行MCP编排,而是自己完成:
- 后端现在运行自己的MCP客户端(`apps/api/src/modules/mcp-client`),直接连接到MCP工具服务器,列出可用工具,并将它们转换为普通的OpenAI **函数工具**定义。
- 聊天请求通过标准的**Chat Completions API** (`/v1/chat/completions`)发送,并附带这些函数工具 - 不涉及`type: 'mcp'`直通。
- 当模型返回`tool_calls`响应时,后端通过MCP客户端执行调用,附加结果为`tool`角色消息,并循环回到模型,直到产生最终答案。
由于这只需要标准的OpenAI函数调用支持,因此它适用于**任何**与OpenAI兼容的后端 - LM Studio、Ollama、llama.cpp、vLLM等 - 而不仅仅是LM Studio。
**因此:**
- LM Studio自己的原生`/api/v1/chat` API在此项目中被禁用,取而代之的是与OpenAI兼容的`/v1/chat/completions`路由,这是与本地推理服务器通信更为标准化的方式。
- OpenAI Responses API (`/v1/responses/create`) 已被禁用,因为它完全依赖于现已损坏的`type: 'mcp'`直通。
- **Chat Completions (`/v1/chat/completions`) 是唯一支持的聊天路径。** 所有新聊天都使用它;现有的Responses-API聊天历史记录仍然可见,但无法继续。
Chat Completions路径的一个已知限制:文件附件仅适用于纯文本(图像内嵌为视觉内容;其他文件类型通过ID引用并按需通过`get-content-from-file-ids`工具获取)- 支持推理努力和AI决定的聊天命名,与旧Responses-API体验匹配。
---
## 架构
```
┌──────────────────────────────────────────────────────────┐
│ Angular UI (port 4200) │
│ OpenAI Chat Completions route │
└────────────────────────────┬──────────────────────────────┘
│ SSE stream
┌────────────────────────────▼──────────────────────────────┐
│ NestJS API (port 8888) │
│ │
│ ┌──────────────┐ ┌────────────────┐ │
│ │ OpenAI │ │ Auth / JWT │ │
│ │ Module │ │ Module │ │
│ └──────┬───────┘ └────────────────┘ │
│ │ tool_calls loop │
│ ┌──────▼───────┐ ┌────────────────┐ ┌────────────────┐│
│ │ McpClient │ │ Chats / │ │ MCP Server ││
│ │ Module │ │ ChatMetadata │ │ (@rekog/mcp- ││
│ │ (MCP client) │◄─┤ MongoDB │ │ nest) ││
│ └──────┬───────┘ │ persistence │ └────────┬───────┘│
│ │ └────────────────┘ ▲ │
│ └──────────── connects as MCP client ─────┘ │
│ ┌─────────────────────────────────────────┐ │
│ │ Assets Module │ │
│ │ Image blobs stored in MongoDB │ │
│ └─────────────────────────────────────────┘ │
└────────────────────────────┬──────────────────────────────┘
│ /v1/chat/completions
┌────────────────────────────▼──────────────────────────────┐
│ Any OpenAI-compatible inference server │
│ LM Studio │ Ollama │ llama.cpp │ vLLM │ ... │
└──────────────────────────────────────────────────────────┘
│ generate-image-tool triggers
┌──────────────────────────▼───────────────────────────────┐
│ InvokeAI (port 9090) │
│ /api/v2/models │ /api/v1/queue/default/enqueue │
│ Socket.IO (/ws/socket.io/) │
└──────────────────────────────────────────────────────────┘
```
与旧的Responses-API流程不同,在那里LM Studio本身连接到MCP服务器进行推理 - 现在NestJS后端充当MCP客户端,列出其自己的MCP服务器的工具,将它们附加到Chat Completions请求中为普通的函数工具,并在模型返回任何`tool_calls`时执行它们,然后循环回到模型。推理服务器永远不会直接与MCP通信,因此这适用于任何支持标准OpenAI函数调用的后端。
---
## 功能
- **与OpenAI兼容的Chat Completions** - 与任何实现`/v1/chat/completions`的后端通信(LM Studio、Ollama、llama.cpp、vLLM、...);LM Studio的原生API和OpenAI Responses API已禁用(参见[上方](#chat-completions-api-current-default))
- **客户端MCP编排** - 后端运行自己的MCP客户端,将MCP工具转换为OpenAI函数工具定义,并在循环中执行`tool_calls`
- **实时SSE流** - 响应以令牌为单位流式传输到浏览器,包括推理增量
- **持久聊天历史记录** - 每个交换都存储在MongoDB中作为滚动消息数组,并在需要时重新加载,包括重建的工具调用横幅和图像附件
- **MCP工具服务器** - 后端将自己注册为MCP服务器,也调用自己作为MCP客户端
- `get-token-usage-tool` - 返回身份验证用户的当前令牌使用情况和限制
- `get-content-from-file-ids` - 按需获取上传的文件内容,文件ID
- `generate-file-from-content-tool` / `generate-zip-from-file-ids` - 让模型生成可下载的文件并将它们捆绑到ZIP中
- `get-image-tool` - 从URL获取图像
- `decrypt-message-tool` - 在推理时解密AES加密的用户消息
- `greeting-tool` - 示例工具,具有进度报告
- `generate-image-tool` - 根据自然语言提示通过InvokeAI生成图像,并将其作为持久资产注入聊天中
- **AI图像生成** - 模型可以在推理期间调用`generate-image-tool`;后端将txt2img作业提交给InvokeAI,下载结果,存储在MongoDB中,并返回聊天的Markdown图像引用
- **图像上传** - 用户可以在发送消息之前附加一个或多个图像;图像通过Assets API上传到MongoDB,并作为视觉内容转发给模型
- **端到端AES消息加密** - 按聊天可选;消息使用CryptoJS AES加密后离开浏览器,模型通过MCP在推理时解密
- **JWT身份验证** - 使用bcrypt哈希密码登录/注册;令牌1小时后过期
- **基于角色的访问控制** - 通过`RolesGuard`实现`User`和`Admin`角色
- **基于订阅的令牌速率限制** - 可配置的令牌预算每个订阅层级(`free` / `basic`),具有自动重置间隔
- **模型选择器** - 动态从运行的LM Studio实例获取可用模型
- **推理模式** - 将推理努力(`off` / `low` / `medium` / `high`)传递给支持的模型
- **Swagger UI** - 可选的OpenAPI文档(通过`USE_SWAGGER=true`启用)
- **Markdown渲染** - 助手响应在聊天UI中渲染为格式化的Markdown
---
## 技术栈
| 层 | 技术 |
| --- | --- |
| 前端 | Angular 21, TailwindCSS 4, RxJS 7 |
| 后端 | NestJS 11, TypeScript 5.9 |
| 数据库 | MongoDB via Mongoose |
| MCP | `@rekog/mcp-nest`(Streamable HTTP + SSE transports) |
| 图像生成 | InvokeAI(本地,通过REST API + Socket.IO) |
| 图像存储 | MongoDB (`image_blobs` collection, binary Buffer) |
| 文件上传 | `@nestjs/platform-express` / Multer(内存存储) |
| 加密 | `crypto-js`(AES) |
| 身份验证 | JWT (`@nestjs/jwt`), bcrypt |
| HTTP客户端 | `@nestjs/axios` |
| OpenAI SDK | `openai` npm包(指向LM Studio base URL) |
| API文档 | Swagger / OpenAPI (`@nestjs/swagger`) |
---
## 项目结构
```
apps/
├── api/ # NestJS后端
│ └── src/
│ ├── app.module.ts # 根模块 — MCP, Mongo, guards
│ ├── main.ts # 启动, CORS, Swagger, body-parser
│ ├── tools/
│ │ └── api.tools.ts # MCP服务器工具(token-usage, file gen/zip, image, decrypt, ...)
│ └── modules/
│ ├── auth/ # JWT身份验证, guards, 用户模式
│ ├── assets/ # 图像大对象存储和检索(MongoDB)
│ ├── chats/ # 聊天消息持久化(Responses entries + Completions消息数组)
│ ├── chat-metadata/ # 会话元数据(模型, 加密配置等)
│ ├── invoke/ # InvokeAI集成(图像生成)
│ ├── lm-studio/ # 原生LM Studio API代理 — 禁用,仅供参考
│ ├── mcp-client/ # MCP客户端 — 连接到MCP服务器,为Chat Completions执行tool_calls
│ ├── openai/ # 与OpenAI兼容的Chat Completions(活动)+ 旧Responses API(禁用)代理
│ └── token-limit/ # 令牌预算跟踪和速率限制强制执行
└── ui/ # Angular前端
└── src/app/
├── app.ts # 根组件 — JWT过期守卫
├── lmstudio-stream.service.ts # LM Studio API的SSE客户端(未使用 — 端点禁用)
├── client/ # 自动生成的API客户端DTO
└── routes/
├── login.ts # 登录/注册页面
├── lm-studio-api/ # 旧聊天界面,用于原生LM Studio端点 — 禁用
│ ├── chat-input.component.ts
│ ├── chat-messages.component.ts # 渲染文本,图像,工具调用(由两个路由共享)
│ ├── chat-sidebar.component.ts
│ ├── model-selector.component.ts
│ └── info.component.ts
└── openai-api/ # Chat UI用于OpenAI Chat Completions端点(活动)+ 旧Responses(禁用)
├── chat-input.component.ts # 包括图像/文件附加按钮
├── chat.service.ts # 旧Responses API聊天状态
├── chat-completions.service.ts # 活动Chat Completions聊天状态
├── openai-stream.service.ts # 旧Responses API的SSE客户端
├── completions-openai-stream.service.ts # Chat Completions的SSE客户端
└── model-selector.component.ts
```
---
## 前提条件
- **Node.js** 18+
- **MongoDB** 在本地运行(默认为`mongodb://localhost:27017/lmStudioWrapper`)或远程URI
- **与OpenAI兼容的推理服务器** 在本地运行,其`/v1` API启用(LM Studio、Ollama、llama.cpp、vLLM、...)- 默认假设LM Studio在`http://localhost:1234`
- 加载支持工具/函数调用的模型以启用MCP功能
- **InvokeAI** (可选)- 仅需用于AI图像生成;默认:`http://127.0.0.1:9090`
---
## 环境变量
在`apps/api/`中创建`.env`文件(或在shell中设置变量):
``` env
# MongoDB连接URI
MONGODB_URI=mongodb://localhost:27017/lmStudioWrapper
# 与OpenAI兼容的推理服务器基准URL(LM Studio、Ollama、llama.cpp、vLLM、...)
LM_STUDIO_BASE_URL=http://localhost:1234
LM_STUDIO_API_TOKEN= # 可选 - 如果您的后端需要令牌,请设置
# JWT签名密钥 - 生产环境中使用长随机字符串
JWT_SECRET=your-very-secret-key
# 后端MCP客户端连接的URL,以便调用MCP工具。
# 这是后端调用自身 — 可以是此机器的localhost/LAN IP
SELF_MCP_URL=http://192.168.0.34:8888/tools/mcp
# 要连接的其他外部MCP服务器列表(可选)
# MCP_SERVER_URLS=http://example.com/mcp,http://another-host:9000/mcp
# 此后端使用的公共基准URL - 用于构造generate-image-tool返回的资产URL
# 必须能从浏览器访问(例如http://localhost:8888或您的LAN IP)
SELF_URL=http://localhost:8888
# 后端HTTP端口(默认:8888)
PORT=8888
# 设置为任意非空值以在/api启用Swagger UI
USE_SWAGGER=true
```
> **注意`SELF_MCP_URL`:** 由于后端的`McpClientService`现在是调用MCP工具的模块(参见[Chat Completions API](#chat-completions-api-current-default)),因此只需要后端进程本身可以访问它 - 不再需要从LM Studio访问。
> **注意`SELF_URL`:** 由`generate-image-tool`用于构建返回聊天的公共图像URL。将其设置为浏览器访问NestJS API的地址。如果省略,资产链接将损坏。
> **注意InvokeAI基准URL:** InvokeAI基准URL当前在`app.module.ts`中硬编码为`http://127.0.0.1:9090`(`InvokeModule.forRoot(...)`)。如果您的InvokeAI实例运行在其他位置,请直接更改此值。
---
## 快速入门
### 1. 安装依赖
```bash
# 从monorepo根目录
npm install
```
### 2. 启动API
```bash
nx serve api
```
API将在`http://localhost:8888`可用。
如果`USE_SWAGGER=true`,Swagger UI将在`http://localhost:8888/api`可用。
### 3. 启动UI
```bash
nx serve ui`
```
UI将在`http://localhost:4200`可用。
### 4. 同时启动两者
```bash
npm start
# 运行:nx run-many --target=serve --projects=api,ui`
```
### 5. 注册用户
使用Swagger UI或发送`POST /auth/register`请求:
```bash
curl -X POST http://localhost:8888/auth/register \
-H "Content-Type: application/json" \
-d '{"username": "alice", "password": "s3cret"}'
```
然后在`POST /auth/login`登录以接收JWT。
## MCP 工具集成

NestJS 后端同时扮演 **MCP 服务器** 和 **MCP 客户端** 的角色:
- **MCP 服务器**(`apps/api/src/tools/api.tools.ts`)— 通过 `@rekog/mcp-nest` 注册,在 `http://localhost:8888/tools/mcp` 处提供可流式传输的 HTTP 和 SSE 传输。
- **MCP 客户端**(`apps/api/src/modules/mcp-client`)— 连接到同一个 MCP 服务器(以及通过 `MCP_SERVER_URLS` 配置的任何其他服务器),列出其工具,并代表模型调用它们。
对于每个聊天完成请求,后端:
1. 调用 `McpClientService.listTools()` 以获取当前的工具列表,并将每个工具转换为普通的 OpenAI 函数工具定义。
2. 通过 `/v1/chat/completions` 发送聊天请求,并附上这些工具。
3. 如果模型响应 `tool_calls`,则通过 `McpClientService.callTool()` 执行每个工具,转发经过身份验证的用户 JWT 和当前 `chatId` 作为 MCP 请求头,以便工具可以完全访问用户上下文。
4. 将工具结果作为 `tool` 角色消息附加,并循环返回到模型,直到它产生最终答案(以 8 次迭代为上限作为安全防护)。
这意味着 MCP 工具与模型服务器可能使用的任何 OpenAI 兼容后端一起工作,而推理服务器本身无需知道 MCP 的存在。
### 可用工具
| 工具 | 描述 |
|------|-------------|
| `get-token-usage-tool` | 返回用户的当前代币消耗、订阅等级、限制和下一次重置时间 |
| `get-content-from-file-ids` | 返回通过文件 ID 以 base64 格式存储的之前上传/生成的 文件内容 |
| `generate-file-from-content-tool` | 从提供的内容中生成可下载的文件,并将其作为资产存储 |
| `generate-zip-from-file-ids` | 将多个先前生成/上传的文件捆绑成可下载的 ZIP 存档 |
| `get-image-tool` | 从 URL 中获取图像,并将其作为资产存储 |
| `decrypt-message-tool` | 使用存储在 `chat_metadata` 中的每个聊天加密密钥解密 AES 加密的用户消息 |
| `greeting-tool` | 示例工具 — 返回带有流式进度更新的问候 |
| `generate-image-tool` | 通过 InvokeAI 从文本提示生成图像,在 MongoDB 中存储,并返回可渲染的聊天图像 URL |
要添加新工具,请在 `apps/api/src/tools/` 中创建一个 `@Injectable()` 类,用 `@rekog/mcp-nest` 中的 `@Tool(...)` 修饰方法,在 `AppModule` 中将该类注册为提供者,并在 `OpenAiService.chatStreamCompletions` 中的 `allowedTools` 列表中添加其名称,以便实际提供给模型。
---
## 图像生成(InvokeAI)
`generate-image-tool` MCP 工具允许语言模型在对话过程中按需生成图像。它需要一个本地运行的 [InvokeAI](https://invoke-ai.github.io/InvokeAI/) 实例。
### 工作原理
1. **工具调用** — 模型使用自然语言 `prompt` 字符串调用 `generate-image-tool`。
2. **模型查找** — `InvokeService` 查询 InvokeAI 的 `/api/v2/models/` 端点,并找到第一个名称包含请求的模型名称(默认为 `"Dreamshaper 8"`)的模型。
3. **作业提交** — 构造一个 txt2img 管道图(512 × 512,30 步,`dpmpp_3m_k` 调度器,CFG 7.5),并通过 `POST /api/v1/queue/default/enqueue_batch` 将其提交到 InvokeAI 的队列中。
4. **Socket.IO 监听器** — 服务打开到 InvokeAI 的 Socket.IO 连接(`/ws/socket.io/`),并订阅 `default` 队列。它等待包含生成图像名称的 `invocation_complete` 事件。
5. **下载和持久化** — 从 InvokeAI 的 `/api/v1/images/i/{name}/full` 端点下载生成的图像,并通过 `AssetsService` 将其存储为 MongoDB 中的二进制大对象。
6. **URL 构造** — 以 `{SELF_URL}/assets/filequery/{filename}?userId=...&chatId=...` 形式将公共资产 URL 返回给模型。模型在聊天中将其渲染为 Markdown 图像引用。
### InvokeAI 配置
InvokeAI 基地址默认为 `http://127.0.0.1:9090`,并在 `AppModule` 中设置:
```typescript
InvokeModule.forRoot('http://127.0.0.1:9090')
```
更改此值以匹配您的 InvokeAI 安装。确保 InvokeAI 加载了至少一个 SD1.x 兼容模型(例如 Dreamshaper 8),以使默认管道正常工作。
---
## 图片上传
用户可以在发送聊天消息之前将图片附加到消息上。上传的图片存储在 MongoDB 中,并作为视觉内容转发给模型。
### 工作原理
1. **前端** — 聊天输入组件(OpenAI API 路由)包含一个 **Attach** 按钮,打开原生文件选择器。可以将多个图片附加到单个消息中。附加文件在文本区域下方以文件名和大小列出;可以在发送之前删除单个文件。
2. **上传** — 在发送时,每个附加图片都以 `multipart/form-data` 的形式发送到 `POST /assets/:chatId`。后端验证 MIME 类型(JPEG、PNG、WebP、GIF、AVIF),将文件大小限制为 **10 MB**,并将原始二进制数据存储在 `image_blobs` MongoDB 集合中。
3. **检索** — 图片通过以下方式提供:
- `GET /assets/:chatId/:filename` — 身份验证端点(使用请求用户的 JWT)
- `GET /assets/filequery/:filename?chatId=...&userId=...` — `generate-image-tool` 返回值使用的公共端点,以便浏览器可以在没有额外身份验证头的情况下显示 AI 生成的图像
4. **聊天中渲染** — 聊天消息组件在用户的消息气泡中内联渲染用户上传的图片。模型以 Markdown 图像标签返回的 AI 生成图片由 Markdown 管道渲染。
### 支持的格式
| 格式 | MIME 类型 |
|--------|-----------|
| JPEG | `image/jpeg`、`image/jpg` |
| PNG | `image/png` |
| WebP | `image/webp` |
| GIF | `image/gif` |
| AVIF | `image/avif` |
最大文件大小:**10 MB** 每文件。
---
## 消息加密
可以在创建新聊天会话时选择每聊 AES-256 消息加密。目标是将明文消息内容排除在推理服务器自己的消息存储/日志之外 — 只有密文被转发到模型服务器。
### 工作原理
加密在两端都由 [CryptoJS](https://github.com/brix/crypto-js)(`crypto-js ^4.2`)使用,通过 CBC 模式的 AES 和仅存储在 MongoDB 中的每个聊天密钥。
**端到端流程:**
1. **会话创建** — 当用户为新聊天启用加密时,会生成一个 `cryptoKey`,并在 `chat_metadata` 文档中存储 `useCrypto: true`。密钥永远不会离开服务器。
2. **消息加密(后端)** — 在将每个请求转发到 LM Studio 之前,`OpenAiService.encryptChatMessage()` 遍历整个输入数组,并用其 AES 密文替换每个明文 `content` 字符串(或内容部分的 `text` 字段):
```plaintext
CryptoJS.AES.encrypt(plaintext, cryptoKey).toString()
```
这意味着 LM Studio 仅接收和存储不透明的密文。
3. **系统提示注入** — 除了加密消息外,后端还会注入一个开发者指令,指示模型:
- **始终** 调用 `decrypt-message-tool`,传递完整的未经修改的用户消息
- 在接收工具响应后完全忽略原始加密输入
- 将解密的文本视为真实用户消息并直接回答
- 在其响应中从不提及解密步骤
4. **推理时 MCP 解密** — LM Studio 通过 `decrypt-message-tool` 调用回 NestJS MCP 服务器。工具接收密文,根据请求中转发的 `chatId` 头查找 `cryptoKey`,并将明文返回给模型:
```plaintext
CryptoJS.AES.decrypt(ciphertext, cryptoKey).toString(CryptoJS.enc.Utf8)
```
5. **透明响应** — 模型以正常方式回答解密后的问题。从用户的角度来看,对话流程与平常一样;加密/解密循环是不可见的。
### 密钥存储和安全边界
| 对象 | 存储位置 | 明文? |
|------|-------|-----------|
| `cryptoKey` | `chat_metadata` MongoDB 文档 | ✅ 是 — 将 MongoDB 视为受信任边界 |
| 转发给 LM Studio 的消息 | LM Studio 消息存储 | ❌ 否 — 始终是密文 |
| 浏览器中的消息 → API 请求 | 到 NestJS 的 HTTP 正文 | ✅ 是 — 生产环境下使用 HTTPS |
| 转发给 MCP 工具的 `chatId` | `chatId` 请求头 | ✅ 是 — 仅用于密钥查找 |
> **安全注意:** 加密旨在保护消息内容不被 LM Studio 自己的对话存储读取。安全边界是您的 NestJS API + MongoDB — 如果这些被泄露,密钥将可访问。在任何非本地部署中使用 HTTPS。
---
## 身份验证和授权
- **注册** — `POST /auth/register` 创建一个具有 bcrypt 哈希密码的用户。新账户在激活链接使用之前处于非活动状态。
- **登录** — `POST /auth/login` 返回一个签名 JWT(1 小时到期)。
- **守卫** — `JwtAuthGuard` 作为 `APP_GUARD` 全局应用。可以为 `@Public()` 装饰器选择退出。
- **角色** — `RolesGuard` 强制执行 `@Roles(Role.Admin)` / `@Roles(Role.User)` 装饰器。
- **令牌自动刷新** — Angular `App` 根组件在每次导航时检查 JWT 到期时间,并在到期时重定向到 `/login`。
---
## 代币使用和速率限制
按用户跟踪代币消耗,并根据在 `token_limit_configs` MongoDB 集合中配置的订阅层限制强制执行。
| 字段 | 描述 |
|-------|-------------|
| `tokensPerInterval` | 在一个重置窗口内允许的最大代币数量 |
| `minutesTillReset` | 计数器重置前的分钟数 |
| `subscription` | 此配置适用的层级(`free` 或 `basic`)|
每次推理完成后,`TokenLimitService.updateUsedTokens()` 都会增加用户的 `usedTokens` 计数器。如果达到限制,则会向客户端发出带有重置时间戳的 `api.info` SSE 事件。计数器在 `tokenCountResetDate` 到达时自动重置。
可以通过 `TokenLimitModule` 控制器管理代币限制。
---
## API 概述
| 方法 | 路径 | 描述 |
|--------|------|-------------|
| `POST` | `/auth/register` | 创建新用户账户 |
| `POST` | `/auth/login` | 认证并接收 JWT |
| `GET` | `/lm-studio/models` | ⚠️ 已禁用 — 通过原生 LM Studio API 列出模型 |
| `POST` | `/lm-studio/chat` | ⚠️ 已禁用 — 非流式聊天(LM Studio 原生 API) |
| `POST` | `/lm-studio/chat/stream` | ⚠️ 已禁用 — 流式 SSE 聊天(LM Studio 原生 API) |
| `GET` | `/openai/models` | 通过 OpenAI SDK 列出模型 |
| `POST` | `/openai/chat-stream` | ⚠️ 已禁用 — 通过 OpenAI **Responses** API 流式 SSE |
| `POST` | `/openai/completions-stream` | ✅ **活跃** — 通过 OpenAI **Chat Completions** API 流式 SSE,带有客户端 MCP 工具编排 |
| `GET` | `/chat-metadata` | 列出用户的聊天会话 |
| `GET` | `/chat-metadata/:id` | 获取单个聊天会话 |
| `POST` | `/chat-metadata` | 创建聊天会话 |
| `PATCH` | `/chat-metadata/:id` | 更新聊天会话 |
| `DELETE` | `/chat-metadata/:id` | 删除聊天会话 |
| `GET` | `/chats/:chatId` | 检索会话的消息 |
| `POST` | `/assets/:chatId` | 上传聊天会话的图片 |
| `GET` | `/assets/:chatId/:filename` | 检索上传的图片(身份验证) |
| `GET` | `/assets/filequery/:filename?chatId=&userId=` | 通过查询参数检索图片(公共,用于 AI 生成的图片) |
| `GET` | `/invoke/test` | 测试端点 — 通过 InvokeAI 生成示例图片 |
| `GET` `/POST` | `/tools/mcp` | MCP 服务器端点(SSE + 流式 HTTP) |
当 `USE_SWAGGER=true` 时,在 `http://localhost:8888/api` 处提供完整的交互式文档。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器