chore: import upstream snapshot with attribution
Ruff Format Check / Ruff Format & Lint (push) Failing after 7m39s
Deploy VitePress site to Pages / build (push) Failing after 9m11s
Deploy VitePress site to Pages / Deploy (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:32:26 +08:00
commit 1443d3fdf9
732 changed files with 196602 additions and 0 deletions
+192
View File
@@ -0,0 +1,192 @@
# API Key 外部集成
Yuxi 平台提供了 API Key 认证机制,允许外部系统在无需用户登录的情况下调用智能体对话接口。本文档详细介绍 API Key 的使用方法、接口调用方式以及安全注意事项。
## API Key 概述
API Key 是一种用于身份验证的密钥字符串,外部系统可以通过它在请求头中携带凭据来访问 Yuxi 的对话接口。与传统的用户名密码登录方式相比,API Key 更加适合用于系统间的自动化调用场景。Yuxi 的 API Key 以 `yxkey_` 为前缀,长度为 54 个字符,采用 SHA-256 哈希存储,确保密钥本身不会在数据库中明文保存。系统会记录每个 API Key 的最后使用时间,方便管理员追踪使用情况。
## 创建 API Key
登录系统后,进入 API Key 管理界面,可以创建新的密钥。创建时需要为 API Key 设置一个名称,用于标识其用途,例如"外部客服系统"或"数据同步服务"。创建的 API Key 会自动绑定到当前登录用户,绑定后的 API Key 在调用接口时会以该用户的身份执行操作。API Key 还支持设置过期时间,过期后该密钥将自动失效。
需要特别注意的是,创建 API Key 时返回的完整密钥(secret)只会显示一次,务必在创建时将其安全保存。如果遗失,需要通过"重新生成"功能生成新的密钥,原有的密钥将立即失效。
管理接口同样走通用认证:
- `GET /api/user/apikey/`:列出当前用户可见的 API Key
- `POST /api/user/apikey/`:创建 API Key
- `PUT /api/user/apikey/{api_key_id}`:更新名称、状态或过期时间
- `POST /api/user/apikey/{api_key_id}/regenerate`:重新生成密钥
- `DELETE /api/user/apikey/{api_key_id}`:删除密钥
## 确定 API 访问地址
Yuxi 后端服务绑定在 `0.0.0.0:5050`,不会自动探测或对外宣告本机 IP。实际访问地址取决于部署环境:
- **本地开发**`http://localhost:5050`
- **生产部署(Nginx 反向代理)**:**强烈建议使用 HTTPS**,即 `https://<服务器域名>`443 端口)。由于 API Key 会在请求头中以明文形式传输,使用 HTTP(80 端口)会导致密钥在网络传输过程中被窃听或篡改,必须避免
完整的 API 交互流程可参考自动生成的 Swagger 文档:`{base_url}/docs`
## 接口调用方式
> **关于 `agent_id` / `agent_slug` 的说明**:创建会话线程时仍使用 `agent_id` 绑定目标 Agent;创建运行任务时使用 `agent_slug` 快照本次运行目标。二者的取值都是智能体的 **slug**(如 `default-chatbot`),不是数据库自增 ID 或 `agent_config_id`。
外部系统通过 HTTP 请求调用 Yuxi 接口时,需要在请求头中携带 API Key:
```http
Authorization: Bearer yxkey_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```
当前智能体对话采用 run + SSE 流程:
1. 创建对话线程:`POST /api/chat/thread`
2. 创建运行任务:`POST /api/agent/runs`
3. 订阅事件流:`GET /api/agent/runs/{run_id}/events`
`POST /api/agent/runs` 请求体必填 `query``agent_slug``thread_id`,可选字段包括 `meta``image_content``resume``created_by_run_id`。接口返回 `run_id``thread_id``status``request_id``stream_url`
以下是一个典型的 Python 调用示例:
```python
import json
import requests
base_url = "https://your-yuxi-server" # 生产环境务必使用 HTTPS;本地开发可改为 http://localhost:5050
headers = {
"Authorization": "Bearer yxkey_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"Content-Type": "application/json",
}
thread_resp = requests.post(
f"{base_url}/api/chat/thread",
headers=headers,
json={
"agent_id": "default-chatbot",
"title": "外部系统会话",
"metadata": {},
},
)
thread_resp.raise_for_status()
thread_id = thread_resp.json()["id"]
run_resp = requests.post(
f"{base_url}/api/agent/runs",
headers=headers,
json={
"query": "你好,请介绍一下你自己",
"agent_slug": "default-chatbot",
"thread_id": thread_id,
"meta": {"request_id": "external-request-001"},
},
)
run_resp.raise_for_status()
run = run_resp.json()
with requests.get(f"{base_url}{run['stream_url']}", headers=headers, stream=True) as response:
response.raise_for_status()
event_type = None
data_lines = []
for line in response.iter_lines(decode_unicode=True):
if line is None:
continue
if line.startswith(":"):
continue
if line == "":
if event_type and data_lines:
payload = json.loads("\n".join(data_lines))
print(event_type, payload)
if event_type == "end":
break
event_type = None
data_lines = []
continue
if line.startswith("event:"):
event_type = line.removeprefix("event:").strip()
elif line.startswith("data:"):
data_lines.append(line.removeprefix("data:").strip())
```
如果已经有会话线程,可以复用已有 `thread_id` 直接创建 run
```json
{
"query": "继续上一轮话题",
"agent_slug": "default-chatbot",
"thread_id": "existing-thread-id",
"meta": {}
}
```
### 读取运行结果
如果不需要逐事件消费 SSE,可以在 run 终态后直接拉取最终结果:
```http
GET /api/agent/runs/{run_id}/result
```
返回结构包含运行状态、最终 assistant 输出、Langfuse trace id 和错误信息。该接口只读,不会再次触发 run。对外部系统只关心「最终答案」、不需要展示中间过程的场景,比订阅 SSE 更简单。
### 外部系统调用入口
除通用 `/api/agent/runs` 之外,Yuxi 还提供专为外部系统设计的 `agent-invocation` 路由,复用同一套 AgentRun 队列与结果读取能力:
| 接口 | 用途 | 关键字段 |
|------|------|----------|
| `POST /api/agent-invocation/agent-call/runs` | 外部系统调用 Agent`async_mode=true` 时立即返回 `run_id`,否则阻塞到 run 终态返回结果 | `agent_slug``messages``thread_id``request_id``model_spec``async_mode` |
| `POST /api/agent-invocation/agent-call/runs/result` | 读取 agent-call run 的 OpenAI 兼容结果结构 | `run_id`、可选 `agent_slug` |
| `POST /api/agent-invocation/eval/runs` | 运行一次评估样例,阻塞到 run 终态后返回最终输出与可选轨迹摘要 | `query``agent_slug``evaluation``include_trajectory_summary` |
agent-call 的 `messages[].content` 兼容 OpenAI 风格的 `text`/`image_url` 多模态数组:纯文本数组不会触发 422,图片输入会保留原始 LangChain 多模态消息供 worker 恢复。出于安全考虑,**不允许通过 `agent_call_meta.context` 覆盖 Agent 运行上下文**;运行时模型覆盖只允许走独立 `model_spec` 字段。Agent Eval 通常通过 `yuxi agent eval` CLI 触发,详见[智能体评估](../agents/agent-evaluation.md)。
## 响应格式
运行事件流采用 Server-Sent Events 格式,响应头为 `text/event-stream`。每个事件包含:
- `event`:事件类型,可能是模型输出、工具调用、子智能体输出等语义事件,也可能是 `error` 或终止事件 `end`
- `data`JSON 编码的事件 envelope,包含 `run_id``thread_id`、事件载荷等字段
- `id`Redis Stream 序号,可作为断线重连游标
服务端还会定期发送以 `:` 开头的 heartbeat 注释,客户端应忽略。断线重连时,可以在请求头中传 `Last-Event-ID`,或在 query 参数中传 `after_seq`,服务端会从该序号后继续回放事件。
事件流默认返回完整载荷,便于排查 LangGraph/Langfuse 运行细节。如果只需要渲染消息、工具调用、工具结果、Agent state 和终止状态,可以在订阅地址追加 `?verbose=false`。精简模式会保留 SSE `event/data/id`、data 中的 `run_id/thread_id/request_id/payload` 以及客户端消费所需字段;同一 data 内的 `request_id` 会外提为单个字段。精简模式还会跳过 `metadata` 和空 `yuxi.agent_state`,并去掉每个 chunk 中重复的 `meta``metadata``thread_id``response`、空 `namespace` 和图片 base64 等调试字段。
每次创建 run 都会返回 `request_id`,可用于日志追踪和问题排查。如果需要在多轮对话中使用同一个会话,请复用 `thread_id`,系统会将同一线程的消息串联起来形成连贯的对话上下文。
## 认证方式
Yuxi 的 API 接口统一支持两种认证方式:
1. **API Key 认证**:使用 `Authorization: Bearer <api_key>` 格式,其中 API Key 必须以 `yxkey_` 前缀开头
2. **JWT Token 认证**:使用 `Authorization: Bearer <jwt_token>` 格式
系统根据 token 的前缀自动判断认证方式。以 `yxkey_` 开头的 token 被视为 API Key,其他 token 则作为 JWT Token 处理。这种设计使得同一个接口可以同时支持外部系统(使用 API Key)和内部前端应用(使用用户登录态)调用。
## 安全注意事项
**传输层安全**:API Key 在请求头中以明文形式传输,**生产环境必须通过 HTTPS(443 端口)调用**,避免在公网上以 HTTP 明文传输造成密钥泄露。建议在 Nginx 反向代理层启用 TLS 并强制 HTTP 重定向到 HTTPS。
保管好 API Key 密钥是最重要的安全原则。由于 API Key 一旦泄露就可能被滥用,建议不要将密钥硬编码在代码中,而是通过环境变量或配置中心来管理。如果怀疑密钥泄露,应立即在管理界面禁用该 API Key 并重新生成。启用密钥过期功能是一种良好的安全实践,可以设置较短的有效期并定期轮换。
在生产环境中,建议为不同的外部系统创建独立的 API Key,这样可以在某个密钥泄露时快速定位问题并限制影响范围。同时,建议在管理界面定期查看 API Key 的使用记录,检查是否存在异常调用情况。
关于权限控制,API Key 的权限等同于其绑定的用户在系统中的角色。如果 API Key 绑定到特定用户,则该用户的所有权限都会体现在 API Key 的操作中,因此务必妥善保管。
## 常见问题
**Q: API Key 认证失败返回什么错误?**
A: 认证失败时返回 401 Unauthorized 错误,错误信息为"无效的凭证"。请检查请求头中 `Authorization` 字段的格式是否正确,是否包含完整的密钥,且密钥必须以 `yxkey_` 开头。
**Q: 可以同时使用 API Key 和 JWT Token 吗?**
A: 不可以。系统根据 token 前缀自动判断认证方式。以 `yxkey_` 开头的 token 使用 API Key 认证,其他 token 使用 JWT 认证。
**Q: API Key 是否有调用频率限制?**
A: 目前没有单独的频率限制,但 API Key 的行为等同于其绑定的用户身份,因此会受到用户角色相关的一些限制。
**Q: 对话返回的内容是乱码怎么办?**
A: 确保客户端正确处理了 UTF-8 编码。流式响应中可能包含中文字符,需要使用正确的编码方式解析。如果在终端显示乱码,可以检查终端的编码设置。
+86
View File
@@ -0,0 +1,86 @@
# 品牌自定义
Yuxi 支持完整的品牌自定义,包括 Logo、组织名称、版权信息、登录协议等,方便企业用户进行品牌定制。
## 品牌信息配置
### 步骤 1:复制模板文件
```bash
cp backend/package/yuxi/config/static/info.template.yaml backend/package/yuxi/config/static/info.local.yaml
```
### 步骤 2:编辑品牌信息
`backend/package/yuxi/config/static/info.local.yaml` 中配置你的品牌信息:
- 应用名称
- 组织名称
- Logo
- 版权信息
- 登录页用户协议/隐私协议链接
### 步骤 3:指定配置文件
`.env` 中指定配置文件路径:
```env
YUXI_BRAND_FILE_PATH=backend/package/yuxi/config/static/info.local.yaml
```
::: tip 配置优先级
`info.local.yaml` > `info.template.yaml`(默认)
:::
## 登录协议配置
登录页支持从品牌配置中读取用户协议与隐私协议链接。
### 配置项
`backend/package/yuxi/config/static/info.local.yaml``footer` 下新增以下字段:
```yaml
footer:
copyright: "© your org 2026"
user_agreement_url: "/protocols/user-agreement.template.html"
privacy_policy_url: "/protocols/privacy-policy.template.html"
```
### 显示规则
-`user_agreement_url``privacy_policy_url` 都有值时,登录页会显示协议勾选项。
- 任一字段为空时,登录页不显示协议勾选项。
- 未勾选协议时,提交登录/初始化会通过消息提示用户先同意协议。
### 协议模板文件
系统默认提供两个 HTML 模板文件:
- `web/public/protocols/user-agreement.template.html`
- `web/public/protocols/privacy-policy.template.html`
你可以直接编辑这两个文件中的协议内容,并替换占位符(如 `{{ORG_NAME}}``{{PRODUCT_NAME}}``{{EFFECTIVE_DATE}}`)。
如果你有自己的协议页面,也可以将 `user_agreement_url``privacy_policy_url` 指向自定义路径或外部链接。
### Icon 定制
系统预设了多种 Icon,如需更多图标,可以从 `lucide-vue-next` 中引入。
## 样式定制
系统支持完整的主题色定制。配置文件位于 `web/src/assets/css/base.css`,以及 `web/src/assets/css/base.dark.css`
```css
:root {
--main-color: #1890ff; /* 主色调 */
--main-1000: #f0f2f5; /* 色板 */
--main-900: #e6f7ff; /* 色板 */
/* ... 其他色板 */
}
```
修改配色变量后,界面会实时更新,无需重启服务。
此外,`web/src/stores/theme.js` 中的 `colorPrimary` 也需要同步修改。
+37
View File
@@ -0,0 +1,37 @@
# 配置系统详解
## 概述
系统采用多层配置架构,模型配置由网页界面管理,应用配置基于 Pydantic + TOML。
## 配置层级
```
代码默认值 → TOML 文件 → 环境变量
(低) (高)
```
## 模型配置
由网页统一管理,详见 [模型配置](../intro/model-config.md)。
## 应用配置
配置项定义于 `backend/package/yuxi/config/app.py`,用户修改保存至 `saves/config/base.toml`
### 修改配置
```python
from yuxi.config import config
config.default_model = "provider-id:model-id"
config.save()
```
配置会在保存 `base.toml` 后写入 Redis 快照(`yuxi:runtime_config`)。快照包含可运行时同步的公开配置字段,不包含 `_` 开头的内部属性和 `save_dir`API/worker 进程在启动时各拉起一个后台同步线程,按 5 秒间隔从该快照刷新内存值,读取端无需感知。Redis 不可用时继续使用当前内存值。
`save_dir` 是启动期内部路径配置,不在管理员配置中展示,也不支持通过管理员配置接口、`base.toml` 或运行时 Redis 快照修改。sandbox 相关配置仍属于启动期敏感配置,运行中的已初始化组件不承诺完整热更新,修改后需要重启服务保证生效。
## 常见问题
**配置文件损坏**:删除 `saves/config/base.toml`,系统将重新生成默认配置。
+83
View File
@@ -0,0 +1,83 @@
# 生产部署指南
本文档介绍如何在生产环境中部署 Yuxi。
## 前置要求
- Docker Engine (v24.0+)
- Docker Compose (v2.20+)
- NVIDIA Container Toolkit(如需使用 GPU 服务)
::: warning 注意事项
1. 生产环境和开发环境建议使用不同的机器,避免端口和资源冲突
2. 虽然名为「生产环境」,但这只是基本配置,真正上线需要根据实际情况调整
3. 前端有调试面板(长按侧边栏触发),生产环境建议关闭
:::
## 部署步骤
### 1. 准备配置文件
为避免与开发环境冲突,生产环境建议使用 `.env.prod` 文件:
```bash
cp .env.template .env.prod
```
编辑 `.env.prod`,设置强密码和必要的 API 密钥:
- `NEO4J_PASSWORD`:修改默认密码
- `MINIO_ACCESS_KEY` / `MINIO_SECRET_KEY`:修改默认密钥
- `SILICONFLOW_API_KEY` 等模型密钥
### 2. 启动服务
使用生产环境配置文件启动:
```bash
# 仅启动核心服务(CPU 模式)
docker compose -f docker-compose.prod.yml up -d --build
# 启动所有服务(包含 GPU OCR)
docker compose -f docker-compose.prod.yml --profile all up -d --build
```
### 3. 验证部署
- Web 访问:http://localhost(直接通过 80 端口)
- API 健康检查:`curl http://localhost/api/system/health`
## 跨域(CORS)配置
`docker-compose.prod.yml` 默认把 `YUXI_ENV` 设为 `production`,后端在该环境下会按 `YUXI_CORS_ORIGINS` 显式声明允许的来源。**未配置时返回空列表,浏览器跨域请求会被拒绝**。生产部署前请根据前端与 API 的相对位置选择策略:
| 部署形态 | 推荐配置 |
|----------|----------|
| 前端与 API 同源(Nginx 同端口反代) | 不需要设置,留空即可 |
| 前端与 API 跨域部署 | `YUXI_CORS_ORIGINS=https://your-frontend.example.com` |
| 多个前端域名 | 逗号分隔,如 `https://a.example.com,https://b.example.com` |
| 完全放开(不推荐) | `YUXI_CORS_ORIGINS=*`,会自动关闭 credentials,登录态/JWT 无法跨域携带 |
开发环境(`YUXI_ENV=development` 且未设置该变量)默认允许 `http://localhost:5173``http://127.0.0.1:5173`,方便本地前后端独立启动调试。从 0.7.0 升级到 0.7.1 时,如果此前是跨域部署但未显式声明来源,必须补上 `YUXI_CORS_ORIGINS`,否则前端跨域请求会被拒绝。
## 维护与更新
### 更新代码
```bash
# 拉取最新代码
git pull
# 重新构建并启动
docker compose -f docker-compose.prod.yml up -d --build
```
### 查看日志
```bash
# API 日志
docker logs -f api-prod
# Nginx 访问日志
docker logs -f web-prod
```
+152
View File
@@ -0,0 +1,152 @@
# 文档处理与 OCR
Yuxi 支持多种文档格式的智能解析,从简单的文本文件到复杂的 PDF 文档,都能自动提取内容并转换为可检索的格式。
## 支持的文件类型
### 常规文档
| 类型 | 格式 | 说明 |
|------|------|------|
| 文本 | .txt, .md, .html, .htm | 直接提取内容 |
| Word | .docx | 保留格式和结构 |
| PowerPoint | .pptx | 保留主要文本结构 |
| PDF | .pdf | 支持文本和图片 PDF |
| 表格 | .csv, .xls, .xlsx | 识别表格结构 |
| JSON | .json | 结构化数据 |
### 图片文件
对于图片文件,需要启用 OCR 才能提取文字:
- .jpg, .jpeg, .png, .bmp, .tiff, .tif
### 压缩包
支持上传 ZIP 压缩包,系统会:
- 自动提取并处理其中的 Markdown 文件
- 处理图片并上传到对象存储
- 智能识别 `full.md` 或第一个 `.md` 文件
### 网页内容
支持通过 URL 直接抓取网页内容:
1. 配置 `YUXI_URL_WHITELIST` 环境变量启用白名单机制
2. 系统自动将 HTML 转换为 Markdown
3. 内置去重机制,避免重复抓取
::: tip URL 白名单配置
示例:`YUXI_URL_WHITELIST=github.com,*.wikipedia.org,docs.python.org`
:::
## OCR 方案选择
系统提供多种 OCR 方案,适用于不同场景:
### 方案对比
| 方案 | 适用场景 | 硬件要求 | 特点 |
|------|----------|----------|------|
| RapidOCR | 基础文字识别 | CPU | 免费开源,速度快 |
| MinerU | 复杂 PDF、表格 | GPU | 精度高,版面分析好 |
| MinerU Official | 复杂文档 | 无 | 官方云服务,开箱即用 |
| PP-Structure-V3 | 表格、票据 | GPU | 专业版面解析 |
| DeepSeek OCR | 智能理解 | 无 | 云端服务,Markdown 输出 |
| PaddleOCR-VL-1.6 | 复杂文档、表格、图片 PDF | 无 | 百度 AI Studio 云端服务,输出 Markdown |
| PP-OCRv6 | 基础文字识别 | 无 | 百度 AI Studio 云端 OCR,输出纯文本 |
### 选择建议
- **个人使用或 CPU 环境**:选择 RapidOCR,免费且资源占用低
- **高精度需求**:选择 MinerU(需要 GPU)或 MinerU Official
- **表格密集型文档**:选择 PP-Structure-V3
- **云端版面解析**:选择 PaddleOCR-VL-1.6,适合希望输出 Markdown 的 PDF 或图片文档
- **云端纯文字识别**:选择 PP-OCRv6,适合只需要提取图片文字的场景
- **简单云服务**:选择 DeepSeek OCR 或 PaddleOCR API
## 快速配置
### RapidOCR
启动后会默认下载,无需配置
### MinerU(高精度)
项目已内置 mineru-api 服务(位于 docker-compose.yml,属于 all profile),无需额外下载官方 compose 文件。首次构建镜像时会基于 docker/mineru.Dockerfile 下载模型,该过程耗时较长。
启动服务(需要 GPU):
```bash
docker compose --profile all up -d --build mineru-api
```
该服务在 `30001` 端口提供 `/file_parse` 接口,后端 `api` / `worker` 默认通过 `MINERU_API_URI=http://mineru-api:30001` 连接,通常无需额外配置。
::: tip 显存不足
若显存有限导致启动失败,可在 `docker-compose.yml``mineru-api` 服务下放开 `--gpu-memory-utilization` 参数(如 `0.5`,必要时进一步降低)。
:::
### MinerU Official(云服务)
从 [MinerU 官网](https://mineru.net) 获取 API 密钥,在 .env 配置环境变量
```env
MINERU_API_KEY=your-api-key-here
```
### PP-Structure-V3(结构化)
启动服务(需要 GPU
```bash
docker compose up paddlex -d
```
### DeepSeek OCR(简单云服务)
在 .env 配置(使用已有的 SiliconFlow 密钥)
```env
SILICONFLOW_API_KEY=your-api-key-here
```
### PaddleOCR API(百度 AI Studio 云服务)
PaddleOCR API 使用百度 AI Studio 的 Access Token。获取方式:
1. 登录 [百度 AI Studio Access Token 页面](https://aistudio.baidu.com/account/accessToken)
2. 在页面中复制 Access Token
3.`.env` 中配置为 `PADDLEOCR_API_TOKEN`
```env
PADDLEOCR_API_TOKEN=your-access-token-here
```
如需使用自定义 PaddleOCR API 地址,可额外配置:
```env
PADDLEOCR_API_URL=https://paddleocr.aistudio-app.com/api/v2/ocr/jobs
```
配置完成后,重启后端服务,在上传文件或解析临时附件时可以选择:
- `PaddleOCR-VL-1.6`:对应 `paddleocr_vl_1_6`,用于文档版面解析,返回 Markdown
- `PP-OCRv6`:对应 `paddleocr_pp_ocrv6`,用于基础 OCR,返回按行拼接的纯文本
## 图片显示配置
上传文档中的图片需要正确配置才能在外部显示:
`.env` 中设置服务器 IP
```
HOST_IP=your_server_ip
```
## 注意事项
1. **图片文件必须启用 OCR**:否则无法提取内容
2. **GPU 要求**MinerU 和 PP-Structure-V3 需要 GPU 支持
3. **API 密钥**MinerU Official、DeepSeek OCR、PaddleOCR API 等云服务需要额外的 API 密钥或 Access Token 配置
4. **超时处理**:复杂文档解析可能耗时较长,可通过 `MINERU_TIMEOUT` 环境变量调整超时时间
5. **文件大小限制**:单个上传文件大小不超过 100 MB
+37
View File
@@ -0,0 +1,37 @@
# Langfuse 集成
## 为什么 Yuxi 需要 Langfuse
Langfuse 是一套面向大模型应用的可观测性平台,适合用来观察一次智能体执行过程中到底发生了什么。在 Yuxi 里,一轮用户消息通常不会只对应一次简单的模型调用,它往往会伴随 LangGraph 图执行、工具调用、知识库检索以及多轮中间状态切换。仅靠普通后端日志,虽然也能定位问题,但往往需要在多个文件和多个服务日志之间来回跳转,阅读成本高,而且很难从用户、线程和智能体三个维度统一查看。Langfuse 的价值就在于,它把这些原本分散的执行细节收拢到同一条 trace 里,让你能够从一次对话出发,回看模型输入输出、工具链路、耗时和错误位置。
在 Yuxi 当前的实现中,Langfuse 主要承担的是智能体执行观测层,而不是业务主流程的一部分。换句话说,它不会替代模型服务,也不会替代聊天接口本身,而是帮助你在智能体已经能够工作的前提下,看清楚它是如何工作的。对于调试复杂 Agent、排查工具调用失败、评估多轮会话质量以及分析不同智能体的耗时与成本来说,这类观测能力非常关键。尤其是在一个线程里连续发生多轮交互时,Langfuse 可以帮助你把“这轮请求是谁发起的、落在哪个 thread、触发了哪个 agent、调用了哪些模型和工具”这些信息统一串起来。
## 在 Yuxi 中能做什么
Yuxi 对 Langfuse 的映射方式比较直接。一个 Yuxi 用户会映射为 Langfuse 中的 `user_id`,一个对话线程会映射为 `session_id`,而每次用户输入触发的一轮智能体执行会形成一条独立的 trace。这样做的好处是,既能按单轮请求排查问题,也能在同一个线程维度下连续查看多轮会话。对于需要长期分析使用质量、成本和延迟的场景,这种映射方式能够兼顾可读性和后续统计需求。
当 Langfuse 与 Yuxi 连通之后,它最直接的作用是帮助你看清一轮智能体请求内部发生了哪些步骤。你可以看到这一轮调用关联的是哪个用户、哪个线程、哪个智能体,也可以进一步观察模型调用、工具调用和整体耗时表现。对于日常调试来说,它让“问题到底出在模型、工具、配置还是图流程”这件事变得更容易判断。对于长期运行的系统来说,它也为后续做延迟分析、成本分析和用户反馈分析提供了统一的观察入口。
用户在对话界面对助手消息提交点赞或点踩后,Yuxi 会继续把反馈保存在本地业务表中;如果该助手消息已经关联 Langfuse trace,则会同步写入 Langfuse score。同步到 Langfuse 的 score 名称为 `user-feedback`,点赞值为 `1`,点踩值为 `0`,点踩原因会作为 score comment 保存,便于在 Langfuse 中按低分反馈筛选和分析具体 trace。
## 如何配置
如果你准备启用 Langfuse,首先需要在 Langfuse Cloud 中创建项目并获取访问凭证。当前版本推荐优先使用云端模式,因为接入成本最低,也更适合先把 tracing 跑通。你需要在运行 Yuxi 的环境中配置 `LANGFUSE_PUBLIC_KEY``LANGFUSE_SECRET_KEY``LANGFUSE_BASE_URL`。其中前两个字段用于鉴权,`LANGFUSE_BASE_URL` 用于指定 Langfuse 服务地址;如果你使用官方云服务,通常可以直接填写 `https://cloud.langfuse.com`。在大多数部署场景下,只要把这些变量写入 `.env` 并通过 Docker Compose 传给 `api` 服务即可生效。
从当前实现来看,Langfuse 只有在 key 配置完整时才会被启用。如果没有配置 `LANGFUSE_PUBLIC_KEY``LANGFUSE_SECRET_KEY`,Yuxi 会自动退化为“不启用 tracing”的状态,正常聊天功能不会因此中断。这意味着 Langfuse 是一个可选增强项,而不是系统启动的前置依赖。对于希望先验证主流程、后续再逐步补全观测能力的部署者来说,这种行为比较友好,因为它降低了接入门槛,也减少了配置错误对主业务的影响。
## 配置后系统会如何工作
理解 Langfuse 的另一个关键点在于,它并不等于“所有调试信息都会立即显示在界面里”。当前 Yuxi 的设计重点是先把 trace id 与执行上下文稳定关联起来,再把这些信息作为后续调试和分析的基础。也正因为如此,系统会优先保证聊天主链路的稳定性,而不是为了获取额外的可点击 URL 去同步等待 Langfuse 的远程接口。换句话说,Langfuse 在 Yuxi 里首先是观测数据的来源,其次才是一个方便跳转查看的外部页面入口。
这也意味着,Langfuse 接入的目标并不是改变用户聊天体验,而是在不破坏主流程稳定性的前提下,为系统补上一层可观测性。只要配置正确,用户的对话仍然按照原有方式执行,只是在后台额外留下可追踪的执行记录。对于运维和开发来说,这类“尽量不影响主流程”的接入方式更适合在现有系统中逐步落地。
## 如何查看是否生效
启用完成后,你最常见的查看方式是在 Langfuse 控制台中按项目查看 traces。进入项目后,可以按照用户、线程、Agent 或时间范围来筛选,定位到某一轮具体的请求。打开单条 trace 之后,你通常可以看到这一轮智能体执行的整体耗时、模型调用、工具调用以及相关 metadata。对于排查问题来说,这比直接翻阅后端日志更高效,因为你不需要自己手动拼装上下文。对于性能分析来说,也可以更直观地看出某个智能体是否在某类请求上耗时异常,或者某个工具是否经常成为慢点。
如果你是系统管理员或开发者,希望快速确认 Yuxi 是否已经成功把 tracing 打到 Langfuse,最简单的方法不是先看代码,而是先发起一条真实对话,再到 Langfuse 控制台中按最近时间排序查看是否出现新的 trace。如果配置正确,你应该可以看到对应线程下新增的一轮执行记录;如果没有看到,则优先检查 `.env` 中的三个关键变量是否正确传入 `api` 容器,以及容器内依赖是否已经包含 Langfuse SDK。对于基于 Docker Compose 的开发环境,这一步尤其重要,因为仅修改 `pyproject.toml` 并不会自动把新依赖装进已经运行中的镜像,通常还需要重新构建或更新容器。
## 当前建议的接入方式
目前 Yuxi 推荐的接入顺序是先完成 tracing,再使用反馈 score 分析用户满意度,后续再扩展到更完整的运营面板。这样做的原因很简单:只有在 trace 关联已经稳定、用户和线程维度映射已经一致的前提下,后续的评分、质量分析和使用统计才会真正可靠。也正因如此,当前文档重点介绍的是 Langfuse 的定位、接入方式和查看路径,而不是一次性覆盖所有更复杂的高级功能。对于大多数项目来说,先把“能看清每轮智能体执行发生了什么”这件事做好,已经能显著改善调试和运维体验。
+83
View File
@@ -0,0 +1,83 @@
# 其他配置
本文档介绍 Yuxi 的其他配置选项,包括内容安全、网页搜索和服务端口等。
## 内容安全
系统内置内容审查机制,帮助保障服务内容的合规性。
### 启用方式
在「系统设置」→「基本设置」页面中配置,可选择启用关键词过滤和 LLM 内容审查。
### 检测流程
系统会在以下时机进行检测:
1. **用户输入检测**:接收到用户消息后立即检测
2. **流式输出检测**:实时检测输出的关键词(仅关键词模式)
3. **输出完成检测**:流式输出结束后进行全面检测
### 检测模式
**关键词检测**
敏感词库位于 `backend/package/yuxi/config/static/bad_keywords.txt`,每行一个关键词。修改后实时生效,无需重启服务。
**LLM 检测**
使用大模型对内容进行审查,可以更好地识别提示词注入等复杂问题,但会增加响应延迟。
::: warning 性能考虑
LLM 检测会增加用户交互的延迟,请根据实际需求选择是否启用。
:::
## 网页搜索
系统集成了 Tavily 联网搜索能力,让大模型能够获取实时网页信息。
### 配置步骤
1. 访问 [Tavily 官网](https://app.tavily.com/) 注册并创建 API Key
2.`.env` 文件中添加:
```env
TAVILY_API_KEY=sk-xxxxxxxxxxxxxxxx
```
3. 重启服务:
```bash
docker compose up -d api-dev web-dev
```
### 使用方式
配置完成后,在智能体的工具配置区域会看到 Tavily 搜索工具。模型会自动判断何时需要调用搜索来获取最新信息。
如需关闭,删除或清空 `TAVILY_API_KEY` 后重启服务即可。
## 服务端口
系统各服务通过以下端口提供访问:
| 端口 | 服务 | 说明 |
|------|------|------|
| 5173 | Web 前端 | 用户界面 |
| 5050 | API 后端 | 核心服务接口 |
| 7474 | Neo4j HTTP | 图数据库管理界面 |
| 7687 | Neo4j Bolt | 图数据库连接 |
| 9000/9001 | MinIO | 对象存储 |
| 19530/9091 | Milvus | 向量数据库 |
| 5432 | PostgreSQL | 业务数据库 |
### 可选服务端口
| 端口 | 服务 | 说明 |
|------|------|------|
| 30000 | MinerU | PDF 解析服务 |
| 8080 | PP-Structure-V3 | OCR 服务 |
| 8081 | vLLM | 本地推理服务 |
### 快速访问
- Web 界面:http://localhost:5173
- API 文档:http://localhost:5050/docs
- Neo4j 管理:http://localhost:7474
+103
View File
@@ -0,0 +1,103 @@
# 第三方登录认证
Yuxi 支持以OIDC接入第三方登录认证,方便企业用户集成现有的身份认证系统。
> 此功能默认关闭,需要在配置文件中启用并提供相关参数。
## 配置步骤
### 1. 前提条件
在你的SSO系统中注册一个新的客户端应用,获取以下信息:
- 客户端IDClient ID
- 客户端密钥(Client Secret
- ISSUER URL
填入回调地址(Redirect URI):https://<your_yuxi_host>/api/auth/oidc/callback
### 2. 配置Yuxi
在Yuxi的.env文件中添加以下配置项:
```sh
# 是否启用 OIDC 认证 (true/false)
# OIDC_ENABLED=false
# 认证源名称(显示在登录按钮上的文字,建议简短且具有辨识度, 默认: OIDC登录)
# OIDC_PROVIDER_NAME="OIDC登录"
# OIDC Provider 的 Issuer URL (例如: https://auth.example.com)
# OIDC_ISSUER_URL=
# OIDC Client ID
# OIDC_CLIENT_ID=
# OIDC Client Secret
# OIDC_CLIENT_SECRET=
# OIDC 回调 URL (可选,默认自动构建为 /api/auth/oidc/callback, 不建议自定义)
# 填写完整的地址:https://<your_yuxi_host>/api/auth/oidc/callback
# 需要确保此 URL 在 OIDC Provider 中已注册
# OIDC_REDIRECT_URI=
# 授权端点 (可选,自动从 discovery 获取)
# OIDC_AUTHORIZATION_ENDPOINT=
# Token 端点 (可选,自动从 discovery 获取)
# OIDC_TOKEN_ENDPOINT=
# UserInfo 端点 (可选,自动从 discovery 获取)
# OIDC_USERINFO_ENDPOINT=
# 登出端点 (可选,自动从 discovery 获取)
# OIDC_END_SESSION_ENDPOINT=
# 请求的 scope (默认: openid profile email)
# OIDC_SCOPES=openid profile email
# 是否自动创建用户 (true/false,默认: true)
# OIDC_AUTO_CREATE_USER=true
# OIDC 用户的默认角色 (user/admin,默认: user)
# OIDC_DEFAULT_ROLE=user
# OIDC 用户的默认部门名称 (默认: OIDC用户)
# OIDC_DEFAULT_DEPARTMENT=OIDC用户
# 用户名映射字段 (默认: preferred_username)
# OIDC_USERNAME_CLAIM=preferred_username
# 邮箱映射字段 (默认: email)
# OIDC_EMAIL_CLAIM=email
# 姓名映射字段 (默认: name)
# OIDC_NAME_CLAIM=name
# 是否使用原始用户名(不带 oidc: 前缀),允许映射到 Yuxi 已有的本地账号 (true/false,默认: false)
# 开启后,OIDC 返回的 username 会直接作为业务登录标识 uid 登录,需要管理员提前创建好用户账号
# OIDC_USE_RAW_USERNAME=false
# 是否从OIDC userinfo 中获取部门信息并自动创建关联部门 (true/false,默认: false)
# OIDC_FETCH_DEPARTMENT_INFO=false
# 部门名称字段映射 (默认: department)
# OIDC_DEPARTMENT_CLAIM=department
# OIDC 登录时是否强制提示用户重新登录 (添加 prompt=login 参数,true/false,默认: true)
# OIDC_FORCE_PROMPT_LOGIN=true
```
### 3. 重启Yuxi服务使配置生效
```bash
docker restart api-dev web-dev
```
## 功能说明
### 使用原始用户名(OIDC_USE_RAW_USERNAME=true
当你需要将 Yuxi 系统中已有的本地账号与 OIDC SSO 绑定,可以开启此选项。
**绑定原理**(无需修改数据库):
系统会创建一个标记为删除的占位用户 `oidc:{sub}:{target_user_id}` 来记录 OIDC sub 与 Yuxi 用户的绑定关系,确保只有绑定过的 OIDC 身份才能登录对应的账号,**防止账号冒用**。其中 `target_user_id` 是数据库中的数值 `users.id`;用户登录标识仍使用字符串 `uid`
### 自动获取部门信息(OIDC_FETCH_DEPARTMENT_INFO=true
开启后,系统会从 OIDC userinfo 中读取部门名称和描述,自动在 Yuxi 中创建部门并将用户关联到该部门。
- 对从 OIDC 获取的部门名称会自动做 `strip()` 去空格,并截断到 50 字符
- 部门描述会自动截断到 255 字符
- 如果部门名称处理后为空,会回退到使用 `OIDC_DEFAULT_DEPARTMENT` 默认部门