初始版本
This commit is contained in:
284
public/docs/ai-agent.md
Normal file
284
public/docs/ai-agent.md
Normal file
@@ -0,0 +1,284 @@
|
||||
# AI 智能体接入指南
|
||||
|
||||
> 集成 OpenClaw AI Agent,实现知识库问答、工作流触发与多模型切换。
|
||||
|
||||
## 🧠 什么是 AI 智能体?
|
||||
|
||||
AI 智能体(AI Agent)是 Websopy 平台的核心能力,它能:
|
||||
|
||||
- 🤖 基于自然语言理解用户意图
|
||||
- 📚 连接你的知识库进行精准问答
|
||||
- 🔗 触发业务工作流执行自动化任务
|
||||
- 🔄 在多个 AI 模型间智能切换
|
||||
|
||||
## 📋 前提条件
|
||||
|
||||
- 已完成 [快速上手](./quickstart.md)
|
||||
- 已开通 AI 功能(控制台 → 开发者中心 → AI 功能)
|
||||
|
||||
## 🚀 接入步骤
|
||||
|
||||
### 第一步:安装 AI SDK
|
||||
|
||||
```bash
|
||||
npm install @websopy/ai-sdk
|
||||
```
|
||||
|
||||
### 第二步:初始化 Agent
|
||||
|
||||
```typescript
|
||||
import { AIAgent } from '@websopy/ai-sdk'
|
||||
|
||||
const agent = new AIAgent({
|
||||
apiKey: process.env.WEBSOPY_API_KEY,
|
||||
// 选择默认模型
|
||||
defaultModel: 'gpt-4',
|
||||
// 可用模型列表
|
||||
models: ['gpt-4', 'claude-3', 'gemini-pro']
|
||||
})
|
||||
```
|
||||
|
||||
### 第三步:创建会话
|
||||
|
||||
```typescript
|
||||
// 创建新的对话会话
|
||||
const session = await agent.createSession({
|
||||
userId: 'user-123',
|
||||
// 关联知识库(可选)
|
||||
knowledgeBaseId: 'kb-abc456',
|
||||
// 会话元数据
|
||||
metadata: {
|
||||
source: 'website',
|
||||
language: 'zh-CN'
|
||||
}
|
||||
})
|
||||
|
||||
console.log('会话 ID:', session.id)
|
||||
```
|
||||
|
||||
### 第四步:发送消息
|
||||
|
||||
```typescript
|
||||
// 发送用户消息
|
||||
const response = await agent.sendMessage(session.id, {
|
||||
content: '我想了解你们的产品价格',
|
||||
// 可选:附加参数
|
||||
context: {
|
||||
userPlan: 'free',
|
||||
priority: 'normal'
|
||||
}
|
||||
})
|
||||
|
||||
console.log('AI 回复:', response.content)
|
||||
console.log('使用模型:', response.model)
|
||||
console.log('置信度:', response.confidence)
|
||||
```
|
||||
|
||||
### 第五步:流式响应(SSE)
|
||||
|
||||
对于需要实时反馈的场景,使用流式输出:
|
||||
|
||||
```typescript
|
||||
const stream = await agent.sendMessageStream(session.id, {
|
||||
content: '写一篇关于 AI 的博客文章'
|
||||
})
|
||||
|
||||
for await (const chunk of stream) {
|
||||
process.stdout.write(chunk.content)
|
||||
}
|
||||
```
|
||||
|
||||
## 📚 知识库集成
|
||||
|
||||
### 创建知识库
|
||||
|
||||
```typescript
|
||||
const kb = await agent.createKnowledgeBase({
|
||||
name: '产品文档',
|
||||
description: '公司产品相关文档',
|
||||
// 向量化模型
|
||||
embeddingModel: 'text-embedding-3-small'
|
||||
})
|
||||
|
||||
// 上传文档
|
||||
await agent.uploadDocument(kb.id, {
|
||||
file: './docs/product-guide.pdf',
|
||||
// 文档元数据
|
||||
metadata: {
|
||||
category: 'documentation',
|
||||
version: '2.0'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 关联知识库问答
|
||||
|
||||
```typescript
|
||||
const response = await agent.sendMessage(session.id, {
|
||||
content: '你们的退款政策是什么?',
|
||||
// 强制从知识库检索
|
||||
retrieveFrom: 'kb-abc456',
|
||||
// 检索参数
|
||||
retrievalConfig: {
|
||||
topK: 5, // 返回前 5 条相关片段
|
||||
scoreThreshold: 0.7 // 相似度阈值
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 🔧 工作流触发
|
||||
|
||||
AI Agent 可以根据对话内容自动触发业务工作流:
|
||||
|
||||
```typescript
|
||||
// 配置意图识别和触发
|
||||
await agent.setIntentHandler(session.id, {
|
||||
intents: [
|
||||
{
|
||||
name: 'create_order',
|
||||
patterns: ['下单', '购买', '创建订单'],
|
||||
action: 'trigger_workflow',
|
||||
workflowId: 'wf-order-create'
|
||||
},
|
||||
{
|
||||
name: 'cancel_subscription',
|
||||
patterns: ['取消订阅', '退订'],
|
||||
action: 'trigger_workflow',
|
||||
workflowId: 'wf-subscription-cancel'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
// 处理工作流结果
|
||||
agent.onWorkflowComplete((result) => {
|
||||
console.log('工作流完成:', result.workflowId)
|
||||
console.log('结果:', result.output)
|
||||
})
|
||||
```
|
||||
|
||||
## 🔄 多模型切换
|
||||
|
||||
### 手动切换
|
||||
|
||||
```typescript
|
||||
// 切换到指定模型
|
||||
await agent.switchModel(session.id, 'claude-3')
|
||||
|
||||
const response = await agent.sendMessage(session.id, {
|
||||
content: '解释量子计算原理'
|
||||
})
|
||||
```
|
||||
|
||||
### 自动路由
|
||||
|
||||
根据任务类型自动选择最优模型:
|
||||
|
||||
```typescript
|
||||
const agent = new AIAgent({
|
||||
apiKey: process.env.WEBSOPY_API_KEY,
|
||||
// 配置自动路由
|
||||
autoRoute: {
|
||||
enabled: true,
|
||||
rules: [
|
||||
{ task: 'coding', models: ['gpt-4', 'claude-3'] },
|
||||
{ task: 'creative', models: ['gpt-4', 'gemini-pro'] },
|
||||
{ task: 'analysis', models: ['claude-3', 'gpt-4'] }
|
||||
]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 📊 高级配置
|
||||
|
||||
### 对话上下文管理
|
||||
|
||||
```typescript
|
||||
// 设置上下文窗口大小
|
||||
agent.setContextWindow(session.id, {
|
||||
maxMessages: 50, // 保留最近 50 条消息
|
||||
maxTokens: 8000 // 最大 token 数
|
||||
})
|
||||
|
||||
// 手动添加系统提示
|
||||
agent.addSystemPrompt(session.id, {
|
||||
role: 'system',
|
||||
content: '你是一个专业的客服助手,说话风格友好、专业。'
|
||||
})
|
||||
```
|
||||
|
||||
### 错误处理与重试
|
||||
|
||||
```typescript
|
||||
const response = await agent.sendMessage(session.id, {
|
||||
content: '复杂问题...'
|
||||
}, {
|
||||
// 重试配置
|
||||
retry: {
|
||||
maxAttempts: 3,
|
||||
delayMs: 1000,
|
||||
backoff: 'exponential'
|
||||
},
|
||||
// 超时配置(毫秒)
|
||||
timeout: 30000
|
||||
})
|
||||
```
|
||||
|
||||
## 🧪 完整示例
|
||||
|
||||
```typescript
|
||||
import { AIAgent } from '@websopy/ai-sdk'
|
||||
|
||||
async function main() {
|
||||
const agent = new AIAgent({
|
||||
apiKey: process.env.WEBSOPY_API_KEY,
|
||||
defaultModel: 'gpt-4'
|
||||
})
|
||||
|
||||
// 创建会话
|
||||
const session = await agent.createSession({
|
||||
userId: 'user-123',
|
||||
knowledgeBaseId: 'kb-product-docs'
|
||||
})
|
||||
|
||||
// 对话循环
|
||||
const messages = [
|
||||
'你好,我想了解一下企业版的功能',
|
||||
'支持私有化部署吗?',
|
||||
'好的,我想试用一下'
|
||||
]
|
||||
|
||||
for (const msg of messages) {
|
||||
const response = await agent.sendMessage(session.id, {
|
||||
content: msg
|
||||
})
|
||||
console.log(`\n👤 用户: ${msg}`)
|
||||
console.log(`🤖 AI: ${response.content}`)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
```
|
||||
|
||||
## ❓ 常见问题
|
||||
|
||||
### Q: 如何查看 API 调用量?
|
||||
|
||||
在控制台 → 开发者中心 → AI 功能,可以查看详细的使用统计。
|
||||
|
||||
### Q: 支持哪些 Embedding 模型?
|
||||
|
||||
目前支持:
|
||||
- `text-embedding-3-small`(推荐,速度快)
|
||||
- `text-embedding-3-large`(高精度)
|
||||
- `text-embedding-ada-002`(兼容性)
|
||||
|
||||
### Q: 知识库检索不到相关内容?
|
||||
|
||||
1. 检查文档是否已成功上传和向量化
|
||||
2. 调整 `scoreThreshold` 降低阈值
|
||||
3. 尝试增加 `topK` 获取更多候选
|
||||
|
||||
---
|
||||
|
||||
**上一步:** [5 分钟快速上手](./quickstart.md)
|
||||
**下一步:** [私有化部署完全指南](./deployment.md)
|
||||
189
public/docs/api-reference.md
Normal file
189
public/docs/api-reference.md
Normal file
@@ -0,0 +1,189 @@
|
||||
# REST API 完整参考
|
||||
|
||||
> 200+ 标准接口文档,覆盖用户、内容、AI、支付等全部模块。
|
||||
|
||||
## 📚 API 概览
|
||||
|
||||
**基础 URL:** `https://api.websopy.com/v1`
|
||||
|
||||
**认证方式:** Bearer Token
|
||||
|
||||
```bash
|
||||
curl -H "Authorization: Bearer YOUR_API_KEY" \
|
||||
https://api.websopy.com/v1/user/profile
|
||||
```
|
||||
|
||||
## 📋 端点列表
|
||||
|
||||
### 用户管理 `/user`
|
||||
|
||||
| 方法 | 端点 | 说明 |
|
||||
|------|------|------|
|
||||
| GET | `/user/profile` | 获取当前用户信息 |
|
||||
| PUT | `/user/profile` | 更新用户信息 |
|
||||
| GET | `/user/settings` | 获取用户设置 |
|
||||
| PUT | `/user/settings` | 更新用户设置 |
|
||||
| POST | `/user/avatar` | 上传头像 |
|
||||
|
||||
### 项目管理 `/projects`
|
||||
|
||||
| 方法 | 端点 | 说明 |
|
||||
|------|------|------|
|
||||
| GET | `/projects` | 列出项目 |
|
||||
| POST | `/projects` | 创建项目 |
|
||||
| GET | `/projects/:id` | 获取项目详情 |
|
||||
| PUT | `/projects/:id` | 更新项目 |
|
||||
| DELETE | `/projects/:id` | 删除项目 |
|
||||
| GET | `/projects/:id/members` | 获取项目成员 |
|
||||
| POST | `/projects/:id/members` | 添加成员 |
|
||||
|
||||
### 文件存储 `/storage`
|
||||
|
||||
| 方法 | 端点 | 说明 |
|
||||
|------|------|------|
|
||||
| GET | `/storage/files` | 列出文件 |
|
||||
| POST | `/storage/upload` | 上传文件 |
|
||||
| GET | `/storage/files/:id` | 获取文件信息 |
|
||||
| DELETE | `/storage/files/:id` | 删除文件 |
|
||||
| GET | `/storage/files/:id/download` | 下载文件 |
|
||||
|
||||
### AI 功能 `/ai`
|
||||
|
||||
| 方法 | 端点 | 说明 |
|
||||
|------|------|------|
|
||||
| POST | `/ai/chat` | 发送对话请求 |
|
||||
| POST | `/ai/chat/stream` | 流式对话 |
|
||||
| GET | `/ai/sessions` | 列出会话 |
|
||||
| POST | `/ai/sessions` | 创建会话 |
|
||||
| GET | `/ai/sessions/:id` | 获取会话详情 |
|
||||
| DELETE | `/ai/sessions/:id` | 删除会话 |
|
||||
| POST | `/ai/knowledge` | 创建知识库 |
|
||||
| POST | `/ai/knowledge/:id/documents` | 添加文档 |
|
||||
|
||||
### 支付 `/payments`
|
||||
|
||||
| 方法 | 端点 | 说明 |
|
||||
|------|------|------|
|
||||
| GET | `/payments/orders` | 列出订单 |
|
||||
| POST | `/payments/orders` | 创建订单 |
|
||||
| GET | `/payments/orders/:id` | 订单详情 |
|
||||
| POST | `/payments/checkout` | 创建结算会话 |
|
||||
| GET | `/payments/subscriptions` | 订阅列表 |
|
||||
|
||||
## 🔍 请求与响应
|
||||
|
||||
### 请求头
|
||||
|
||||
```http
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
Content-Type: application/json
|
||||
Accept: application/json
|
||||
X-Request-ID: unique-request-id
|
||||
```
|
||||
|
||||
### 分页
|
||||
|
||||
```http
|
||||
GET /projects?page=2&limit=20
|
||||
```
|
||||
|
||||
响应包含分页信息:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [...],
|
||||
"pagination": {
|
||||
"page": 2,
|
||||
"limit": 20,
|
||||
"total": 100,
|
||||
"total_pages": 5
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 排序
|
||||
|
||||
```http
|
||||
GET /projects?sort=created_at&order=desc
|
||||
```
|
||||
|
||||
### 过滤
|
||||
|
||||
```http
|
||||
GET /projects?status=active&category=ai
|
||||
```
|
||||
|
||||
## 📝 错误处理
|
||||
|
||||
### 错误码
|
||||
|
||||
| 状态码 | 错误码 | 说明 |
|
||||
|--------|--------|------|
|
||||
| 400 | `INVALID_REQUEST` | 请求参数错误 |
|
||||
| 401 | `UNAUTHORIZED` | 未认证或 Token 无效 |
|
||||
| 403 | `FORBIDDEN` | 无权限访问 |
|
||||
| 404 | `NOT_FOUND` | 资源不存在 |
|
||||
| 429 | `RATE_LIMITED` | 请求过于频繁 |
|
||||
| 500 | `SERVER_ERROR` | 服务器内部错误 |
|
||||
|
||||
### 错误响应格式
|
||||
|
||||
```json
|
||||
{
|
||||
"error": {
|
||||
"code": "INVALID_REQUEST",
|
||||
"message": "参数 'name' 不能为空",
|
||||
"details": {
|
||||
"field": "name",
|
||||
"constraint": "required"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 使用示例
|
||||
|
||||
### JavaScript/TypeScript
|
||||
|
||||
```typescript
|
||||
const response = await fetch('https://api.websopy.com/v1/projects', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: '我的项目',
|
||||
description: '项目描述'
|
||||
})
|
||||
})
|
||||
|
||||
const data = await response.json()
|
||||
console.log(data)
|
||||
```
|
||||
|
||||
### Python
|
||||
|
||||
```python
|
||||
import requests
|
||||
|
||||
response = requests.post(
|
||||
'https://api.websopy.com/v1/projects',
|
||||
headers={
|
||||
'Authorization': f'Bearer {api_key}',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
json={
|
||||
'name': '我的项目',
|
||||
'description': '项目描述'
|
||||
}
|
||||
)
|
||||
|
||||
data = response.json()
|
||||
print(data)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**上一步:** [Webhook 事件接入](./webhook.md)
|
||||
**下一步:** [RAG 知识库搭建](./rag.md)
|
||||
211
public/docs/apikey.md
Normal file
211
public/docs/apikey.md
Normal file
@@ -0,0 +1,211 @@
|
||||
# API Key 创建与管理
|
||||
|
||||
> 在控制台创建 API Key,了解权限范围与速率限制,安全使用建议。
|
||||
|
||||
## 🔑 什么是 API Key?
|
||||
|
||||
API Key 是调用 Websopy API 的凭证,类似于「数字身份证」,用于:
|
||||
|
||||
- ✅ 身份认证 - 证明你是平台用户
|
||||
- ✅ 权限控制 - 控制可以访问哪些资源
|
||||
- ✅ 用量统计 - 记录 API 调用情况
|
||||
- ✅ 计费依据 - 按使用量进行计费
|
||||
|
||||
## 📋 创建 API Key
|
||||
|
||||
### 步骤 1:进入控制台
|
||||
|
||||
1. 登录 [Websopy 控制台](https://console.websopy.com)
|
||||
2. 导航到 **开发者中心 → API Key**
|
||||
3. 点击 **创建新 Key**
|
||||
|
||||
### 步骤 2:配置 Key
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|--------|------|
|
||||
| **名称** | 给 Key 取个易识别的名字,如「生产环境」「测试用」 |
|
||||
| **权限范围** | 选择 Key 允许的操作(见下文) |
|
||||
| **有效期** | 设置过期时间(可选) |
|
||||
| **IP 白名单** | 限制只有指定 IP 才能使用(可选) |
|
||||
|
||||
### 步骤 3:保存 Key
|
||||
|
||||
⚠️ **重要**:API Key 只显示一次,请立即:
|
||||
1. 复制保存到安全位置
|
||||
2. 设置环境变量
|
||||
|
||||
```bash
|
||||
# Linux/macOS
|
||||
echo 'export WEBSOPY_API_KEY="ws_live_xxxxx"' >> ~/.bashrc
|
||||
source ~/.bashrc
|
||||
|
||||
# Windows PowerShell
|
||||
[Environment]::SetEnvironmentVariable("WEBSOPY_API_KEY", "ws_live_xxxxx", "User")
|
||||
```
|
||||
|
||||
## 🛡️ 权限范围
|
||||
|
||||
### 可用权限
|
||||
|
||||
| 权限 | 说明 | 适用场景 |
|
||||
|------|------|----------|
|
||||
| `user:read` | 读取用户信息 | 数据展示 |
|
||||
| `user:write` | 修改用户信息 | 用户管理 |
|
||||
| `project:read` | 读取项目 | 数据展示 |
|
||||
| `project:write` | 创建/修改/删除项目 | 项目管理 |
|
||||
| `storage:read` | 读取文件 | 文件读取 |
|
||||
| `storage:write` | 上传/删除文件 | 文件管理 |
|
||||
| `ai:agent` | 使用 AI 智能体 | AI 功能 |
|
||||
| `ai:knowledge` | 管理知识库 | 知识库管理 |
|
||||
| `payment:read` | 读取账单 | 账单查看 |
|
||||
| `admin:*` | 所有权限 | ⚠️ 仅管理员 |
|
||||
|
||||
### 权限组合
|
||||
|
||||
推荐按最小权限原则配置:
|
||||
|
||||
```json
|
||||
// 只读权限(安全)
|
||||
{
|
||||
"permissions": ["user:read", "project:read", "storage:read"]
|
||||
}
|
||||
|
||||
// 读写权限(一般开发)
|
||||
{
|
||||
"permissions": ["user:read", "user:write", "project:*", "storage:*"]
|
||||
}
|
||||
|
||||
// AI 功能
|
||||
{
|
||||
"permissions": ["ai:agent", "ai:knowledge"]
|
||||
}
|
||||
```
|
||||
|
||||
## 🚫 IP 白名单
|
||||
|
||||
增强安全性,限制只有指定 IP 可以使用 Key:
|
||||
|
||||
1. 创建/编辑 Key 时开启「IP 白名单」
|
||||
2. 添加允许的 IP 地址或 CIDR 范围
|
||||
|
||||
```text
|
||||
# 支持的格式
|
||||
203.0.113.1 # 单个 IP
|
||||
203.0.113.0/24 # IP 段
|
||||
203.0.113.1,198.51.100.0/24 # 多个,用逗号分隔
|
||||
```
|
||||
|
||||
## ⏱️ 速率限制
|
||||
|
||||
| 套餐 | 请求限制 |
|
||||
|------|----------|
|
||||
| 免费版 | 100 次/分钟 |
|
||||
| 专业版 | 1,000 次/分钟 |
|
||||
| 企业版 | 10,000 次/分钟 |
|
||||
|
||||
### 查看当前用量
|
||||
|
||||
```typescript
|
||||
const client = new WebsopyClient({
|
||||
apiKey: process.env.WEBSOPY_API_KEY
|
||||
})
|
||||
|
||||
// 获取当前配额
|
||||
const quota = await client.account.getQuota()
|
||||
console.log('今日剩余:', quota.remaining)
|
||||
console.log('重置时间:', quota.resetAt)
|
||||
```
|
||||
|
||||
### 处理限流
|
||||
|
||||
```typescript
|
||||
async function callWithRetry(fn, maxRetries = 3) {
|
||||
for (let i = 0; i < maxRetries; i++) {
|
||||
try {
|
||||
return await fn()
|
||||
} catch (error) {
|
||||
if (error.code === 'RATE_LIMIT_EXCEEDED') {
|
||||
// 等待后重试
|
||||
await sleep(error.retryAfter * 1000)
|
||||
continue
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms))
|
||||
}
|
||||
```
|
||||
|
||||
## 🔐 安全最佳实践
|
||||
|
||||
### ✅ 推荐做法
|
||||
|
||||
```typescript
|
||||
// 1. 使用环境变量,不硬编码
|
||||
const client = new WebsopyClient({
|
||||
apiKey: process.env.WEBSOPY_API_KEY // ✅ 正确
|
||||
})
|
||||
|
||||
// ❌ 危险:硬编码在代码中
|
||||
const client = new WebsopyClient({
|
||||
apiKey: 'ws_live_xxxxx' // ❌ 危险
|
||||
})
|
||||
```
|
||||
|
||||
```typescript
|
||||
// 2. 区分不同环境的 Key
|
||||
const client = new WebsopyClient({
|
||||
apiKey: process.env.NODE_ENV === 'production'
|
||||
? process.env.WEBSOPY_API_KEY_PROD
|
||||
: process.env.WEBSOPY_API_KEY_DEV
|
||||
})
|
||||
```
|
||||
|
||||
```typescript
|
||||
// 3. 前端使用受限 Key
|
||||
const client = new WebsopyClient({
|
||||
apiKey: process.env.WEBSOPY_API_KEY_PUBLIC,
|
||||
// 前端 Key 应该只开只读权限
|
||||
allowedMethods: ['user.getProfile', 'project.list']
|
||||
})
|
||||
```
|
||||
|
||||
### ❌ 避免事项
|
||||
|
||||
1. **不要**将 Key 提交到代码仓库
|
||||
2. **不要**在前端暴露有写权限的 Key
|
||||
3. **不要**使用同一个 Key 处理所有业务
|
||||
4. **不要**通过 URL 参数传递 Key
|
||||
|
||||
```gitignore
|
||||
# .gitignore
|
||||
.env
|
||||
.env.*
|
||||
*.local
|
||||
```
|
||||
|
||||
## 🔄 Key 轮换
|
||||
|
||||
定期更换 API Key 是个好习惯:
|
||||
|
||||
1. 在控制台创建新 Key
|
||||
2. 更新所有使用旧 Key 的地方
|
||||
3. 验证新 Key 正常工作
|
||||
4. 禁用或删除旧 Key
|
||||
|
||||
## 📊 审计日志
|
||||
|
||||
在控制台查看 API Key 的使用记录:
|
||||
|
||||
- 调用时间、频率
|
||||
- 调用的接口
|
||||
- 请求来源 IP
|
||||
- 错误情况
|
||||
|
||||
---
|
||||
|
||||
**上一步:** [安装 SDK 与初始化](./sdk-installation.md)
|
||||
**下一步:** [流式输出(SSE)接入](./streaming.md)
|
||||
393
public/docs/deployment.md
Normal file
393
public/docs/deployment.md
Normal file
@@ -0,0 +1,393 @@
|
||||
# 私有化部署完全指南
|
||||
|
||||
> Docker Compose 一键部署,HTTPS 配置、备份策略与版本升级。
|
||||
|
||||
## 🏠 什么是私有化部署?
|
||||
|
||||
私有化部署让你在自己的服务器上运行 Websopy 平台,享受:
|
||||
|
||||
- 🔒 **数据完全自主** - 所有数据存储在你的服务器
|
||||
- ⚙️ **完全可控** - 自定义配置、插件、界面
|
||||
- 💰 **成本可控** - 无按调用量计费
|
||||
- 🏢 **合规无忧** - 满足数据不出网要求
|
||||
|
||||
## 📋 系统要求
|
||||
|
||||
### 最低配置
|
||||
|
||||
| 资源 | 最低要求 |
|
||||
|------|----------|
|
||||
| CPU | 4 核 |
|
||||
| 内存 | 8 GB |
|
||||
| 硬盘 | 100 GB SSD |
|
||||
| 系统 | Ubuntu 20.04+ / CentOS 8+ |
|
||||
|
||||
### 推荐配置
|
||||
|
||||
| 资源 | 推荐配置 |
|
||||
|------|----------|
|
||||
| CPU | 8 核+ |
|
||||
| 内存 | 16 GB+ |
|
||||
| 硬盘 | 500 GB SSD+ |
|
||||
| 系统 | Ubuntu 22.04 LTS |
|
||||
|
||||
### 软件依赖
|
||||
|
||||
- Docker 20.10+
|
||||
- Docker Compose 2.0+
|
||||
- Git
|
||||
- 域名(可选,用于 HTTPS)
|
||||
|
||||
## 🚀 开始部署
|
||||
|
||||
### 第一步:准备服务器
|
||||
|
||||
```bash
|
||||
# 更新系统
|
||||
sudo apt update && sudo apt upgrade -y
|
||||
|
||||
# 安装 Docker(Ubuntu/Debian)
|
||||
curl -fsSL https://get.docker.com | sh
|
||||
sudo usermod -aG docker $USER
|
||||
|
||||
# 安装 Docker Compose
|
||||
sudo apt install docker-compose -y
|
||||
|
||||
# 验证安装
|
||||
docker --version
|
||||
docker-compose --version
|
||||
```
|
||||
|
||||
### 第二步:下载部署包
|
||||
|
||||
```bash
|
||||
# 创建工作目录
|
||||
mkdir -p ~/websopy && cd ~/websopy
|
||||
|
||||
# 下载最新版本
|
||||
wget https://releases.websopy.com/on-premise/latest.tar.gz
|
||||
|
||||
# 解压
|
||||
tar -xzf latest.tar.gz
|
||||
cd websopy-deploy
|
||||
```
|
||||
|
||||
### 第三步:配置环境
|
||||
|
||||
```bash
|
||||
# 复制配置文件
|
||||
cp .env.example .env
|
||||
|
||||
# 编辑配置文件
|
||||
nano .env
|
||||
```
|
||||
|
||||
关键配置项:
|
||||
|
||||
```env
|
||||
# 版本配置
|
||||
WEBSOPY_VERSION=latest
|
||||
|
||||
# 数据库配置
|
||||
DB_HOST=postgres
|
||||
DB_PORT=5432
|
||||
DB_NAME=websopy
|
||||
DB_USER=websopy
|
||||
DB_PASSWORD=your-secure-password
|
||||
|
||||
# Redis 配置
|
||||
REDIS_HOST=redis
|
||||
REDIS_PORT=6379
|
||||
REDIS_PASSWORD=your-redis-password
|
||||
|
||||
# 域名配置(可选)
|
||||
DOMAIN=your-domain.com
|
||||
HTTPS_ENABLED=true
|
||||
|
||||
# 管理员账户
|
||||
ADMIN_EMAIL=admin@yourcompany.com
|
||||
ADMIN_PASSWORD=your-admin-password
|
||||
```
|
||||
|
||||
### 第四步:启动服务
|
||||
|
||||
```bash
|
||||
# 拉取镜像
|
||||
docker-compose pull
|
||||
|
||||
# 启动所有服务
|
||||
docker-compose up -d
|
||||
|
||||
# 查看服务状态
|
||||
docker-compose ps
|
||||
```
|
||||
|
||||
**预期输出:**
|
||||
|
||||
```
|
||||
NAME STATUS
|
||||
websopy-app running
|
||||
websopy-worker running
|
||||
websopy-postgres running
|
||||
websopy-redis running
|
||||
websopy-nginx running
|
||||
```
|
||||
|
||||
### 第五步:访问平台
|
||||
|
||||
服务启动后,通过浏览器访问:
|
||||
|
||||
- 前端界面:`http://your-server-ip:80`
|
||||
- 管理后台:`http://your-server-ip:80/admin`
|
||||
- API 端点:`http://your-server-ip:8080/api/v1`
|
||||
|
||||
首次登录使用配置的 `ADMIN_EMAIL` 和 `ADMIN_PASSWORD`。
|
||||
|
||||
## 🔒 HTTPS 配置
|
||||
|
||||
### 使用 Let's Encrypt(推荐)
|
||||
|
||||
```bash
|
||||
# 编辑 nginx 配置
|
||||
nano nginx/conf.d/ssl.conf
|
||||
```
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name your-domain.com;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
|
||||
|
||||
# 其他配置...
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name your-domain.com;
|
||||
return 301 https://$server_name$request_uri;
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
# 申请 SSL 证书
|
||||
certbot --nginx -d your-domain.com
|
||||
|
||||
# 重启 nginx
|
||||
docker-compose restart nginx
|
||||
```
|
||||
|
||||
### 使用自有证书
|
||||
|
||||
```bash
|
||||
# 创建证书目录
|
||||
mkdir -p nginx/ssl
|
||||
|
||||
# 复制证书文件
|
||||
cp your-cert.crt nginx/ssl/cert.pem
|
||||
cp your-cert.key nginx/ssl/key.pem
|
||||
```
|
||||
|
||||
## 💾 备份策略
|
||||
|
||||
### 自动备份脚本
|
||||
|
||||
创建 `backup.sh`:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
BACKUP_DIR=/data/backups/websopy
|
||||
DATE=$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
# 创建备份目录
|
||||
mkdir -p $BACKUP_DIR
|
||||
|
||||
# 备份数据库
|
||||
docker exec websopy-postgres pg_dump -U websopy > $BACKUP_DIR/db_$DATE.sql
|
||||
|
||||
# 备份上传文件
|
||||
tar -czf $BACKUP_DIR/uploads_$DATE.tar.gz /data/websopy/uploads
|
||||
|
||||
# 备份配置
|
||||
tar -czf $BACKUP_DIR/config_$DATE.tar.gz /data/websopy/config
|
||||
|
||||
# 保留最近 30 天的备份
|
||||
find $BACKUP_DIR -mtime +30 -delete
|
||||
|
||||
echo "备份完成: $DATE"
|
||||
```
|
||||
|
||||
```bash
|
||||
# 添加执行权限
|
||||
chmod +x backup.sh
|
||||
|
||||
# 设置定时任务(每天凌晨 3 点执行)
|
||||
crontab -e
|
||||
# 添加行: 0 3 * * * /data/websopy/backup.sh >> /var/log/backup.log 2>&1
|
||||
```
|
||||
|
||||
### 数据恢复
|
||||
|
||||
```bash
|
||||
# 停止服务
|
||||
docker-compose down
|
||||
|
||||
# 恢复数据库
|
||||
docker exec -i websopy-postgres psql -U websopy < db_backup_file.sql
|
||||
|
||||
# 恢复上传文件
|
||||
tar -xzf uploads_backup.tar.gz -C /data/websopy/uploads
|
||||
|
||||
# 重启服务
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## 🔄 版本升级
|
||||
|
||||
### 查看当前版本
|
||||
|
||||
```bash
|
||||
docker exec websopy-app websopy --version
|
||||
```
|
||||
|
||||
### 升级步骤
|
||||
|
||||
```bash
|
||||
cd ~/websopy
|
||||
|
||||
# 1. 备份当前数据(必须!)
|
||||
./backup.sh
|
||||
|
||||
# 2. 下载新版本
|
||||
wget https://releases.websopy.com/on-premise/v2.3.0.tar.gz
|
||||
tar -xzf v2.3.0.tar.gz
|
||||
|
||||
# 3. 更新环境变量(如有必要)
|
||||
nano .env
|
||||
# 检查新版本的配置变更
|
||||
|
||||
# 4. 拉取新镜像
|
||||
docker-compose pull
|
||||
|
||||
# 5. 执行数据库迁移
|
||||
docker-compose run --rm websopy-app websopy migrate
|
||||
|
||||
# 6. 重启服务
|
||||
docker-compose up -d
|
||||
|
||||
# 7. 验证升级
|
||||
docker-compose logs -f websopy-app
|
||||
```
|
||||
|
||||
### 紧急回滚
|
||||
|
||||
```bash
|
||||
# 1. 停止当前版本
|
||||
docker-compose down
|
||||
|
||||
# 2. 切换回旧版本
|
||||
git checkout v2.2.0
|
||||
|
||||
# 3. 恢复数据库
|
||||
docker exec -i websopy-postgres psql -U websopy < db_backup_file.sql
|
||||
|
||||
# 4. 启动旧版本
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## 🔧 性能优化
|
||||
|
||||
### 资源调整
|
||||
|
||||
编辑 `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
websopy-app:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2'
|
||||
memory: 4G
|
||||
reservations:
|
||||
cpus: '1'
|
||||
memory: 2G
|
||||
|
||||
websopy-worker:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '4'
|
||||
memory: 8G
|
||||
```
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### PostgreSQL 优化
|
||||
|
||||
```bash
|
||||
docker exec websopy-postgres psql -U websopy -c "
|
||||
ALTER SYSTEM SET shared_buffers = '2GB';
|
||||
ALTER SYSTEM SET effective_cache_size = '6GB';
|
||||
ALTER SYSTEM SET maintenance_work_mem = '512MB';
|
||||
ALTER SYSTEM SET checkpoint_completion_target = 0.9;
|
||||
"
|
||||
|
||||
docker-compose restart postgres
|
||||
```
|
||||
|
||||
## 🐛 常见问题
|
||||
|
||||
### Q: 服务启动失败?
|
||||
|
||||
```bash
|
||||
# 查看日志
|
||||
docker-compose logs -f
|
||||
|
||||
# 检查端口占用
|
||||
netstat -tlnp | grep -E '80|443|5432|6379'
|
||||
```
|
||||
|
||||
### Q: 数据库连接失败?
|
||||
|
||||
1. 检查 `DB_PASSWORD` 是否正确
|
||||
2. 确认 postgres 容器是否正常运行
|
||||
3. 查看 postgres 日志:`docker-compose logs postgres`
|
||||
|
||||
### Q: 内存不足?
|
||||
|
||||
```bash
|
||||
# 查看内存使用
|
||||
docker stats
|
||||
|
||||
# 增加 swap
|
||||
sudo fallocate -l 4G /swapfile
|
||||
sudo chmod 600 /swapfile
|
||||
sudo mkswap /swapfile
|
||||
sudo swapon /swapfile
|
||||
```
|
||||
|
||||
### Q: 如何完全卸载?
|
||||
|
||||
```bash
|
||||
# 停止服务
|
||||
docker-compose down -v
|
||||
|
||||
# 删除数据(谨慎!)
|
||||
rm -rf ~/websopy
|
||||
docker system prune -a
|
||||
```
|
||||
|
||||
## 📞 获取帮助
|
||||
|
||||
- 📧 邮件支持:support@websopy.com
|
||||
- 💬 技术社区:[forum.websopy.com](https://forum.websopy.com)
|
||||
- 📖 官方文档:[docs.websopy.com](https://docs.websopy.com)
|
||||
|
||||
---
|
||||
|
||||
**上一步:** [AI 智能体接入指南](./ai-agent.md)
|
||||
**下一步:** [安装 SDK 与初始化](./sdk-installation.md)
|
||||
278
public/docs/docker.md
Normal file
278
public/docs/docker.md
Normal file
@@ -0,0 +1,278 @@
|
||||
# Docker Compose 部署
|
||||
|
||||
> 一键部署全套服务(前端+后端+数据库+AI),本地与云端通用。
|
||||
|
||||
## 🐳 什么是 Docker Compose?
|
||||
|
||||
Docker Compose 是一个工具,用于定义和运行多容器 Docker 应用。通过一个 `docker-compose.yml` 文件,你可以一键启动所有相关服务。
|
||||
|
||||
## 📋 前提条件
|
||||
|
||||
- Docker 20.10+
|
||||
- Docker Compose 2.0+
|
||||
- 至少 4GB 内存
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 第一步:下载模板
|
||||
|
||||
```bash
|
||||
# 克隆模板仓库
|
||||
git clone https://github.com/websopy/deploy-templates.git websopy-deploy
|
||||
cd websopy-deploy
|
||||
|
||||
# 选择版本
|
||||
git checkout v2.3.0
|
||||
```
|
||||
|
||||
### 第二步:配置环境
|
||||
|
||||
```bash
|
||||
# 复制环境变量文件
|
||||
cp .env.example .env
|
||||
|
||||
# 编辑配置
|
||||
nano .env
|
||||
```
|
||||
|
||||
关键配置:
|
||||
|
||||
```env
|
||||
# 版本
|
||||
WEBSOPY_VERSION=2.3.0
|
||||
|
||||
# 数据库
|
||||
POSTGRES_DB=websopy
|
||||
POSTGRES_USER=websopy
|
||||
POSTGRES_PASSWORD=your-strong-password
|
||||
|
||||
# Redis
|
||||
REDIS_PASSWORD=your-redis-password
|
||||
|
||||
# JWT 密钥(生成随机字符串)
|
||||
JWT_SECRET=$(openssl rand -hex 32)
|
||||
|
||||
# 域名(可选)
|
||||
DOMAIN=your-domain.com
|
||||
```
|
||||
|
||||
### 第三步:启动服务
|
||||
|
||||
```bash
|
||||
# 一键启动所有服务
|
||||
docker-compose up -d
|
||||
|
||||
# 查看服务状态
|
||||
docker-compose ps
|
||||
|
||||
# 查看日志
|
||||
docker-compose logs -f
|
||||
```
|
||||
|
||||
### 第四步:验证部署
|
||||
|
||||
```bash
|
||||
# 检查服务健康状态
|
||||
curl http://localhost:3000/api/health
|
||||
|
||||
# 预期输出
|
||||
{"status":"ok","version":"2.3.0","services":{"db":"up","redis":"up","ai":"up"}}
|
||||
```
|
||||
|
||||
## 🏗️ 服务架构
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ Nginx │
|
||||
│ (反向代理) │
|
||||
└──────┬──────┘
|
||||
│
|
||||
┌───────────────┼───────────────┐
|
||||
│ │ │
|
||||
┌────▼────┐ ┌─────▼────┐ ┌────▼────┐
|
||||
│ Web │ │ API │ │ Worker │
|
||||
│ (前端) │ │ (后端) │ │ (异步) │
|
||||
└─────────┘ └─────┬────┘ └─────────┘
|
||||
│
|
||||
┌────────────┼────────────┐
|
||||
│ │ │
|
||||
┌────▼───┐ ┌─────▼────┐ ┌───▼────┐
|
||||
│Postgres│ │ Redis │ │ AI │
|
||||
│(数据库) │ │ (缓存) │ │(AI服务) │
|
||||
└────────┘ └──────────┘ └────────┘
|
||||
```
|
||||
|
||||
## 📁 目录结构
|
||||
|
||||
```
|
||||
websopy-deploy/
|
||||
├── docker-compose.yml # 服务编排文件
|
||||
├── .env # 环境变量
|
||||
├── nginx/
|
||||
│ └── conf.d/ # Nginx 配置
|
||||
├── postgres/
|
||||
│ └── init.sql # 数据库初始化脚本
|
||||
└── backups/ # 备份目录
|
||||
```
|
||||
|
||||
## 🔧 常用命令
|
||||
|
||||
### 启动与停止
|
||||
|
||||
```bash
|
||||
# 启动所有服务
|
||||
docker-compose up -d
|
||||
|
||||
# 停止所有服务
|
||||
docker-compose down
|
||||
|
||||
# 重启所有服务
|
||||
docker-compose restart
|
||||
|
||||
# 重启指定服务
|
||||
docker-compose restart api
|
||||
```
|
||||
|
||||
### 日志查看
|
||||
|
||||
```bash
|
||||
# 查看所有日志
|
||||
docker-compose logs -f
|
||||
|
||||
# 查看特定服务日志
|
||||
docker-compose logs -f api
|
||||
docker-compose logs -f web
|
||||
|
||||
# 查看最近 100 行
|
||||
docker-compose logs --tail=100
|
||||
```
|
||||
|
||||
### 进入容器
|
||||
|
||||
```bash
|
||||
# 进入 API 容器
|
||||
docker-compose exec api sh
|
||||
|
||||
# 进入数据库
|
||||
docker-compose exec postgres psql -U websopy
|
||||
```
|
||||
|
||||
## 💾 数据持久化
|
||||
|
||||
数据存储在 Docker volumes 中:
|
||||
|
||||
```bash
|
||||
# 查看 volumes
|
||||
docker volume ls | grep websopy
|
||||
|
||||
# 备份数据
|
||||
docker-compose exec postgres pg_dump -U websopy > backup.sql
|
||||
|
||||
# 恢复数据
|
||||
docker exec -i $(docker-compose ps -q postgres) psql -U websopy < backup.sql
|
||||
```
|
||||
|
||||
## 🔄 常用配置
|
||||
|
||||
### 调整资源
|
||||
|
||||
```yaml
|
||||
# docker-compose.yml
|
||||
services:
|
||||
api:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '2'
|
||||
memory: 4G
|
||||
|
||||
worker:
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
cpus: '4'
|
||||
memory: 8G
|
||||
```
|
||||
|
||||
### 自定义端口
|
||||
|
||||
```yaml
|
||||
services:
|
||||
nginx:
|
||||
ports:
|
||||
- "80:80"
|
||||
- "443:443"
|
||||
# 改成本地其他端口
|
||||
# - "8080:80"
|
||||
```
|
||||
|
||||
### 启用 HTTPS
|
||||
|
||||
```bash
|
||||
# 复制 SSL 证书
|
||||
mkdir -p nginx/ssl
|
||||
cp your-cert.crt nginx/ssl/cert.pem
|
||||
cp your-cert.key nginx/ssl/key.pem
|
||||
|
||||
# 编辑 nginx 配置
|
||||
nano nginx/conf.d/default.conf
|
||||
```
|
||||
|
||||
## 🐛 故障排查
|
||||
|
||||
### 服务无法启动
|
||||
|
||||
```bash
|
||||
# 1. 检查 Docker 是否运行
|
||||
docker info
|
||||
|
||||
# 2. 查看详细日志
|
||||
docker-compose up
|
||||
|
||||
# 3. 检查端口占用
|
||||
lsof -i :80
|
||||
```
|
||||
|
||||
### 数据库连接失败
|
||||
|
||||
```bash
|
||||
# 1. 检查 postgres 是否运行
|
||||
docker-compose ps postgres
|
||||
|
||||
# 2. 查看数据库日志
|
||||
docker-compose logs postgres
|
||||
|
||||
# 3. 测试连接
|
||||
docker-compose exec postgres psql -U websopy -c "SELECT 1"
|
||||
```
|
||||
|
||||
### 前端无法访问
|
||||
|
||||
```bash
|
||||
# 1. 检查 nginx 日志
|
||||
docker-compose logs nginx
|
||||
|
||||
# 2. 检查 web 容器
|
||||
docker-compose logs web
|
||||
|
||||
# 3. 重建前端
|
||||
docker-compose up -d --force-recreate web
|
||||
```
|
||||
|
||||
## 🧹 清理
|
||||
|
||||
```bash
|
||||
# 停止并删除容器
|
||||
docker-compose down
|
||||
|
||||
# 删除数据卷(谨慎!)
|
||||
docker-compose down -v
|
||||
|
||||
# 完全清理
|
||||
docker system prune -a
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**上一步:** [AI 工作流配置](./workflow.md)
|
||||
**下一步:** [版本升级与回滚](./upgrade.md)
|
||||
47
public/docs/index.md
Normal file
47
public/docs/index.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# 开发教程
|
||||
|
||||
> 从快速上手到深度定制,全面的开发指引与最佳实践。
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
适合新用户,5 分钟内体验平台核心功能。
|
||||
|
||||
| 教程 | 时长 | 难度 |
|
||||
|------|------|------|
|
||||
| [5 分钟快速上手](./quickstart.md) | 5 分钟 | 入门 |
|
||||
| [安装 SDK 与初始化](./sdk-installation.md) | 5 分钟 | 入门 |
|
||||
| [API Key 创建与管理](./apikey.md) | 5 分钟 | 入门 |
|
||||
|
||||
## 🔌 API 参考
|
||||
|
||||
学习如何调用平台 API,掌握数据交互。
|
||||
|
||||
| 教程 | 时长 | 难度 |
|
||||
|------|------|------|
|
||||
| [REST API 完整参考](./api-reference.md) | 参考手册 | 进阶 |
|
||||
| [流式输出(SSE)接入](./streaming.md) | 10 分钟 | 进阶 |
|
||||
| [Webhook 事件接入](./webhook.md) | 15 分钟 | 进阶 |
|
||||
|
||||
## 🤖 AI 功能
|
||||
|
||||
集成 AI 能力,构建智能应用。
|
||||
|
||||
| 教程 | 时长 | 难度 |
|
||||
|------|------|------|
|
||||
| [AI 智能体 API 接入](./ai-agent.md) | 20 分钟 | 进阶 |
|
||||
| [RAG 知识库搭建](./rag.md) | 30 分钟 | 高级 |
|
||||
| [AI 工作流配置](./workflow.md) | 25 分钟 | 高级 |
|
||||
|
||||
## 🚢 部署运维
|
||||
|
||||
私有化部署、升级与运维指南。
|
||||
|
||||
| 教程 | 时长 | 难度 |
|
||||
|------|------|------|
|
||||
| [Docker Compose 部署](./docker.md) | 30 分钟 | 高级 |
|
||||
| [私有化部署完全指南](./deployment.md) | 30 分钟 | 高级 |
|
||||
| [版本升级与回滚](./upgrade.md) | 20 分钟 | 高级 |
|
||||
|
||||
---
|
||||
|
||||
[← 返回教程列表](../index.md)
|
||||
128
public/docs/quickstart.md
Normal file
128
public/docs/quickstart.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# 5 分钟快速上手
|
||||
|
||||
> 本教程将带你完成 Websopy SDK 的安装、配置,并发送你的第一个 API 请求。
|
||||
|
||||
## 📋 前提条件
|
||||
|
||||
- Node.js 16.x 或更高版本
|
||||
- npm 8.x 或 yarn 1.22+
|
||||
- 一个 Websopy 账户([立即注册](https://websopy.com/register))
|
||||
|
||||
## 🚀 开始
|
||||
|
||||
### 第一步:安装 SDK
|
||||
|
||||
```bash
|
||||
# 使用 npm
|
||||
npm install @websopy/sdk
|
||||
|
||||
# 或使用 yarn
|
||||
yarn add @websopy/sdk
|
||||
|
||||
# 或使用 pnpm
|
||||
pnpm add @websopy/sdk
|
||||
```
|
||||
|
||||
### 第二步:获取 API Key
|
||||
|
||||
1. 登录 [Websopy 控制台](https://console.websopy.com)
|
||||
2. 进入 **开发者中心 → API Key**
|
||||
3. 点击 **创建新 Key**
|
||||
4. 选择权限范围(建议先选择「只读」权限测试)
|
||||
5. 复制生成的 Key(注意:Key 只显示一次,请妥善保存)
|
||||
|
||||
### 第三步:初始化客户端
|
||||
|
||||
```typescript
|
||||
import { WebsopyClient } from '@websopy/sdk'
|
||||
|
||||
const client = new WebsopyClient({
|
||||
apiKey: 'your-api-key-here',
|
||||
// 可选:指定 API 端点
|
||||
baseUrl: 'https://api.websopy.com/v1'
|
||||
})
|
||||
```
|
||||
|
||||
### 第四步:发送第一个请求
|
||||
|
||||
```typescript
|
||||
async function main() {
|
||||
try {
|
||||
// 获取用户信息
|
||||
const user = await client.user.getProfile()
|
||||
console.log('当前用户:', user.name)
|
||||
|
||||
// 创建第一个项目
|
||||
const project = await client.project.create({
|
||||
name: '我的第一个项目',
|
||||
description: '通过 API 创建'
|
||||
})
|
||||
console.log('项目创建成功:', project.id)
|
||||
|
||||
// 获取项目列表
|
||||
const projects = await client.project.list()
|
||||
console.log('项目总数:', projects.total)
|
||||
} catch (error) {
|
||||
console.error('请求失败:', error.message)
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
```
|
||||
|
||||
### 第五步:运行代码
|
||||
|
||||
```bash
|
||||
npx ts-node your-script.ts
|
||||
# 或
|
||||
node your-script.js
|
||||
```
|
||||
|
||||
**预期输出:**
|
||||
|
||||
```
|
||||
当前用户: 张三
|
||||
项目创建成功: proj_abc123xyz
|
||||
项目总数: 5
|
||||
```
|
||||
|
||||
## 🎉 恭喜!
|
||||
|
||||
你已经成功发送了第一个 API 请求。接下来你可以:
|
||||
|
||||
- 📖 继续阅读 [API Key 创建与管理](./apikey.md)
|
||||
- 🔌 查看 [REST API 完整参考](./api-reference.md)
|
||||
- 🤖 尝试 [AI 智能体接入](./ai-agent.md)
|
||||
|
||||
## ⚠️ 常见问题
|
||||
|
||||
### Q: 报 "Invalid API Key" 错误?
|
||||
|
||||
检查以下几点:
|
||||
1. API Key 是否正确复制(不要有空格)
|
||||
2. Key 是否已过期或被禁用
|
||||
3. Key 的权限范围是否包含当前操作
|
||||
|
||||
### Q: 报 "Rate Limit Exceeded" 错误?
|
||||
|
||||
免费账户默认 100 次/分钟。如需更高配额,在控制台升级套餐。
|
||||
|
||||
### Q: 如何开启调试模式?
|
||||
|
||||
```typescript
|
||||
const client = new WebsopyClient({
|
||||
apiKey: 'your-api-key',
|
||||
debug: true // 打印详细请求日志
|
||||
})
|
||||
```
|
||||
|
||||
## 📚 相关资源
|
||||
|
||||
- [SDK 源码仓库](https://github.com/websopy/sdk)
|
||||
- [示例代码集合](https://github.com/websopy/examples)
|
||||
- [API 状态页](https://status.websopy.com)
|
||||
|
||||
---
|
||||
|
||||
**上一步:** [返回教程首页](../index.md)
|
||||
**下一步:** [API Key 创建与管理](./apikey.md)
|
||||
269
public/docs/rag.md
Normal file
269
public/docs/rag.md
Normal file
@@ -0,0 +1,269 @@
|
||||
# RAG 知识库搭建
|
||||
|
||||
> 上传文档、向量化存储,构建企业级知识库问答系统。
|
||||
|
||||
## 🧠 什么是 RAG?
|
||||
|
||||
RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合「知识检索」和「AI 生成」的技术:
|
||||
|
||||
1. **检索**:从知识库中找到相关内容
|
||||
2. **增强**:将检索结果作为上下文
|
||||
3. **生成**:让 AI 基于上下文生成答案
|
||||
|
||||
```
|
||||
用户问题 → 检索相关文档 → 拼接到 Prompt → AI 生成回答
|
||||
```
|
||||
|
||||
## 📋 适用场景
|
||||
|
||||
- 📄 企业内部文档问答
|
||||
- 🎯 产品 FAQ 自动化
|
||||
- 📚 培训资料检索
|
||||
- 🔍 合同/政策查询
|
||||
- 🏥 专业知识库
|
||||
|
||||
## 🚀 搭建步骤
|
||||
|
||||
### 第一步:创建知识库
|
||||
|
||||
```typescript
|
||||
const knowledgeBase = await client.ai.createKnowledgeBase({
|
||||
name: '产品使用手册',
|
||||
description: '公司产品相关文档',
|
||||
// 向量化模型
|
||||
embeddingModel: 'text-embedding-3-small',
|
||||
// 分块策略
|
||||
chunking: {
|
||||
type: 'recursive',
|
||||
chunkSize: 1000,
|
||||
chunkOverlap: 200
|
||||
}
|
||||
})
|
||||
|
||||
console.log('知识库 ID:', knowledgeBase.id)
|
||||
```
|
||||
|
||||
### 第二步:上传文档
|
||||
|
||||
支持格式:PDF、Word、TXT、Markdown、HTML
|
||||
|
||||
```typescript
|
||||
// 上传单个文件
|
||||
const doc = await client.ai.uploadDocument(knowledgeBase.id, {
|
||||
file: './docs/user-guide.pdf',
|
||||
metadata: {
|
||||
category: 'manual',
|
||||
version: '2.0',
|
||||
language: 'zh-CN'
|
||||
}
|
||||
})
|
||||
|
||||
console.log('文档 ID:', doc.id)
|
||||
console.log('状态:', doc.status) // processing → ready
|
||||
|
||||
// 批量上传
|
||||
const docs = await client.ai.uploadDocuments(knowledgeBase.id, [
|
||||
{ file: './docs/faq.md', metadata: { category: 'faq' } },
|
||||
{ file: './docs/api.md', metadata: { category: 'api' } },
|
||||
{ file: './docs/tutorial.md', metadata: { category: 'tutorial' } }
|
||||
])
|
||||
```
|
||||
|
||||
### 第三步:等待处理
|
||||
|
||||
文档需要经过:
|
||||
1. **解析**:提取文本内容
|
||||
2. **分块**:按策略切分成小块
|
||||
3. **向量化**:转成数学向量
|
||||
|
||||
```typescript
|
||||
// 查询文档状态
|
||||
const status = await client.ai.getDocumentStatus(doc.id)
|
||||
console.log('处理状态:', status.processing_status)
|
||||
console.log('块数量:', status.chunk_count)
|
||||
```
|
||||
|
||||
### 第四步:配置检索
|
||||
|
||||
```typescript
|
||||
await client.ai.configureRetrieval(knowledgeBase.id, {
|
||||
// 检索参数
|
||||
retrieval: {
|
||||
topK: 5, // 返回前 5 条
|
||||
scoreThreshold: 0.7, // 相似度阈值
|
||||
hybridSearch: true // 混合搜索(关键词+向量)
|
||||
},
|
||||
// Rerank 配置
|
||||
rerank: {
|
||||
enabled: true,
|
||||
model: 'bge-reranker'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 第五步:问答
|
||||
|
||||
```typescript
|
||||
const response = await client.ai.ask({
|
||||
knowledgeBaseId: knowledgeBase.id,
|
||||
question: '如何创建新项目?',
|
||||
// 可选参数
|
||||
options: {
|
||||
maxTokens: 1000,
|
||||
temperature: 0.7,
|
||||
includeSources: true // 返回引用的文档片段
|
||||
}
|
||||
})
|
||||
|
||||
console.log('回答:', response.answer)
|
||||
console.log('引用:', response.citations)
|
||||
```
|
||||
|
||||
### 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"answer": "创建新项目的步骤如下:\n1. 点击「新建项目」按钮\n2. 填写项目名称和描述\n3. 选择项目模板\n4. 点击「创建」完成",
|
||||
"citations": [
|
||||
{
|
||||
"document_id": "doc_abc123",
|
||||
"chunk_text": "点击「新建项目」按钮,进入项目创建页面...",
|
||||
"score": 0.95
|
||||
}
|
||||
],
|
||||
"model": "gpt-4",
|
||||
"tokens_used": 850
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 高级配置
|
||||
|
||||
### 自定义分块策略
|
||||
|
||||
```typescript
|
||||
const kb = await client.ai.createKnowledgeBase({
|
||||
name: '技术文档',
|
||||
chunking: {
|
||||
type: 'custom',
|
||||
// 按标题分块
|
||||
delimiters: ['# ', '## ', '### '],
|
||||
maxTokens: 500
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 元数据过滤
|
||||
|
||||
```typescript
|
||||
const response = await client.ai.ask({
|
||||
knowledgeBaseId: knowledgeBase.id,
|
||||
question: '退款政策是什么?',
|
||||
filters: {
|
||||
category: 'policy',
|
||||
version: '>=2.0'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 多知识库查询
|
||||
|
||||
```typescript
|
||||
const response = await client.ai.ask({
|
||||
knowledgeBaseIds: ['kb-product', 'kb-faq', 'kb-manual'],
|
||||
question: '这个功能如何使用?',
|
||||
// 权重配置
|
||||
weights: {
|
||||
'kb-product': 0.5,
|
||||
'kb-faq': 0.3,
|
||||
'kb-manual': 0.2
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 📊 知识库管理
|
||||
|
||||
### 查看统计
|
||||
|
||||
```typescript
|
||||
const stats = await client.ai.getKnowledgeBaseStats(knowledgeBase.id)
|
||||
|
||||
console.log('文档数:', stats.document_count)
|
||||
console.log('块数:', stats.chunk_count)
|
||||
console.log('总 token 数:', stats.total_tokens)
|
||||
```
|
||||
|
||||
### 更新文档
|
||||
|
||||
```typescript
|
||||
// 重新上传会自动更新
|
||||
await client.ai.updateDocument(doc.id, {
|
||||
file: './docs/user-guide-v3.pdf'
|
||||
})
|
||||
```
|
||||
|
||||
### 删除文档
|
||||
|
||||
```typescript
|
||||
await client.ai.deleteDocument(doc.id)
|
||||
```
|
||||
|
||||
## 🧪 最佳实践
|
||||
|
||||
### 文档准备
|
||||
|
||||
1. ✅ 清理格式,移除无关内容
|
||||
2. ✅ 添加目录和标题结构
|
||||
3. ✅ QA 格式文档效果最好
|
||||
4. ❌ 避免过长的无结构文本
|
||||
5. ❌ 避免大量表格(难以正确分块)
|
||||
|
||||
### 检索优化
|
||||
|
||||
```typescript
|
||||
// 调整检索参数
|
||||
const optimalConfig = {
|
||||
topK: 3, // 不要太多,可能引入噪音
|
||||
scoreThreshold: 0.75, // 设置合理阈值
|
||||
enableRerank: true // 启用重排序
|
||||
}
|
||||
```
|
||||
|
||||
### Prompt 工程
|
||||
|
||||
```typescript
|
||||
const response = await client.ai.ask({
|
||||
knowledgeBaseId: knowledgeBase.id,
|
||||
question: '...',
|
||||
systemPrompt: `你是一个专业客服,请基于给定的知识库内容回答用户问题。
|
||||
- 如果知识库中没有相关内容,请如实告知
|
||||
- 回答要简洁、专业、易懂
|
||||
- 适当引用原文帮助用户理解`
|
||||
})
|
||||
```
|
||||
|
||||
## ❓ 常见问题
|
||||
|
||||
### Q: 检索不到相关内容?
|
||||
|
||||
1. 检查文档是否处理完成(状态为 `ready`)
|
||||
2. 降低 `scoreThreshold` 阈值
|
||||
3. 尝试 `hybridSearch: true` 混合搜索
|
||||
4. 增加 `topK` 获取更多候选
|
||||
|
||||
### Q: 回答不准确?
|
||||
|
||||
1. 检查源文档质量
|
||||
2. 调整 `chunkSize`,太小可能丢失上下文
|
||||
3. 启用 `rerank` 提高相关性
|
||||
4. 优化 system prompt
|
||||
|
||||
### Q: 处理速度慢?
|
||||
|
||||
- 小文档使用更快的 embedding 模型
|
||||
- 避开高峰期处理大批量文档
|
||||
- 使用异步处理(Webhooks 通知)
|
||||
|
||||
---
|
||||
|
||||
**上一步:** [REST API 完整参考](./api-reference.md)
|
||||
**下一步:** [AI 工作流配置](./workflow.md)
|
||||
207
public/docs/sdk-installation.md
Normal file
207
public/docs/sdk-installation.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# 安装 SDK 与初始化
|
||||
|
||||
> 详细指南:安装 @websopy/sdk,配置 WebsopyClient,发送第一个 API 请求。
|
||||
|
||||
## 📦 SDK 概述
|
||||
|
||||
Websopy 提供多种语言的 SDK:
|
||||
|
||||
| 语言 | SDK | 源码 |
|
||||
|------|-----|------|
|
||||
| JavaScript/TypeScript | `@websopy/sdk` | [GitHub](https://github.com/websopy/sdk-js) |
|
||||
| Python | `websopy-sdk` | [GitHub](https://github.com/websopy/sdk-python) |
|
||||
| Go | `github.com/websopy/sdk-go` | [GitHub](https://github.com/websopy/sdk-go) |
|
||||
| Java | `com.websopy:sdk` | [GitHub](https://github.com/websopy/sdk-java) |
|
||||
|
||||
本教程以 JavaScript/TypeScript 为例。
|
||||
|
||||
## 🚀 安装
|
||||
|
||||
### npm
|
||||
|
||||
```bash
|
||||
npm install @websopy/sdk
|
||||
```
|
||||
|
||||
### yarn
|
||||
|
||||
```bash
|
||||
yarn add @websopy/sdk
|
||||
```
|
||||
|
||||
### pnpm
|
||||
|
||||
```bash
|
||||
pnpm add @websopy/sdk
|
||||
```
|
||||
|
||||
### CDN(浏览器端)
|
||||
|
||||
```html
|
||||
<script src="https://unpkg.com/@websopy/sdk/dist/websopy.min.js"></script>
|
||||
```
|
||||
|
||||
## ⚙️ 初始化配置
|
||||
|
||||
### 基本配置
|
||||
|
||||
```typescript
|
||||
import { WebsopyClient } from '@websopy/sdk'
|
||||
|
||||
const client = new WebsopyClient({
|
||||
apiKey: 'ws_live_xxxxxxxxxxxx',
|
||||
// API 版本(可选,默认 v1)
|
||||
version: 'v1',
|
||||
// 超时时间(毫秒)
|
||||
timeout: 30000,
|
||||
// 重试次数
|
||||
retries: 3
|
||||
})
|
||||
```
|
||||
|
||||
### 多环境配置
|
||||
|
||||
```typescript
|
||||
const config = {
|
||||
// 开发环境
|
||||
dev: {
|
||||
apiKey: 'ws_test_xxxxx',
|
||||
baseUrl: 'https://api-dev.websopy.com/v1'
|
||||
},
|
||||
// 生产环境
|
||||
prod: {
|
||||
apiKey: process.env.WEBSOPY_API_KEY,
|
||||
baseUrl: 'https://api.websopy.com/v1'
|
||||
}
|
||||
}
|
||||
|
||||
const client = new WebsopyClient(
|
||||
process.env.NODE_ENV === 'production' ? config.prod : config.dev
|
||||
)
|
||||
```
|
||||
|
||||
### 环境变量
|
||||
|
||||
创建 `.env` 文件:
|
||||
|
||||
```env
|
||||
WEBSOPY_API_KEY=ws_live_xxxxxxxxxxxx
|
||||
WEBSOPY_BASE_URL=https://api.websopy.com/v1
|
||||
WEBSOPY_TIMEOUT=30000
|
||||
```
|
||||
|
||||
```typescript
|
||||
import 'dotenv/config'
|
||||
import { WebsopyClient } from '@websopy/sdk'
|
||||
|
||||
const client = new WebsopyClient({
|
||||
apiKey: process.env.WEBSOPY_API_KEY,
|
||||
baseUrl: process.env.WEBSOPY_BASE_URL
|
||||
})
|
||||
```
|
||||
|
||||
## 📚 API 模块
|
||||
|
||||
SDK 按功能模块组织:
|
||||
|
||||
```typescript
|
||||
// 用户管理
|
||||
client.user
|
||||
|
||||
// 项目管理
|
||||
client.project
|
||||
|
||||
// 文件存储
|
||||
client.storage
|
||||
|
||||
// AI 功能
|
||||
client.ai
|
||||
|
||||
// 支付功能
|
||||
client.payment
|
||||
|
||||
// Webhook
|
||||
client.webhook
|
||||
```
|
||||
|
||||
## 🧪 完整示例
|
||||
|
||||
```typescript
|
||||
import { WebsopyClient } from '@websopy/sdk'
|
||||
|
||||
async function demo() {
|
||||
const client = new WebsopyClient({
|
||||
apiKey: process.env.WEBSOPY_API_KEY
|
||||
})
|
||||
|
||||
// 1. 获取用户信息
|
||||
const user = await client.user.getProfile()
|
||||
console.log('用户:', user.name)
|
||||
|
||||
// 2. 列出项目
|
||||
const { items: projects } = await client.project.list({
|
||||
limit: 10,
|
||||
status: 'active'
|
||||
})
|
||||
|
||||
// 3. 创建项目
|
||||
const project = await client.project.create({
|
||||
name: '新项目',
|
||||
description: '通过 SDK 创建'
|
||||
})
|
||||
|
||||
// 4. 上传文件
|
||||
const file = await client.storage.upload({
|
||||
file: './demo.pdf',
|
||||
folder: 'documents'
|
||||
})
|
||||
|
||||
console.log('文件上传成功:', file.url)
|
||||
}
|
||||
|
||||
demo().catch(console.error)
|
||||
```
|
||||
|
||||
## 🔧 TypeScript 类型
|
||||
|
||||
SDK 提供完整的 TypeScript 类型定义:
|
||||
|
||||
```typescript
|
||||
import type {
|
||||
Project,
|
||||
User,
|
||||
CreateProjectOptions
|
||||
} from '@websopy/sdk/types'
|
||||
|
||||
function createProject(options: CreateProjectOptions): Promise<Project> {
|
||||
return client.project.create(options)
|
||||
}
|
||||
```
|
||||
|
||||
## ❓ 常见问题
|
||||
|
||||
### Q: ESM 和 CommonJS 兼容?
|
||||
|
||||
是的,SDK 同时支持两种模块格式:
|
||||
|
||||
```typescript
|
||||
// ESM
|
||||
import { WebsopyClient } from '@websopy/sdk'
|
||||
|
||||
// CommonJS
|
||||
const { WebsopyClient } = require('@websopy/sdk')
|
||||
```
|
||||
|
||||
### Q: 如何调试?
|
||||
|
||||
```typescript
|
||||
const client = new WebsopyClient({
|
||||
apiKey: process.env.WEBSOPY_API_KEY,
|
||||
debug: true // 打印详细日志
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**上一步:** [5 分钟快速上手](./quickstart.md)
|
||||
**下一步:** [API Key 创建与管理](./apikey.md)
|
||||
326
public/docs/streaming.md
Normal file
326
public/docs/streaming.md
Normal file
@@ -0,0 +1,326 @@
|
||||
# 流式输出(SSE)接入
|
||||
|
||||
> 使用 Server-Sent Events 实现 AI 流式响应,提升用户体验。
|
||||
|
||||
## 🌊 什么是流式输出?
|
||||
|
||||
流式输出(Streaming)是一种数据传输方式,服务器将数据「分块」发送给客户端,而不是等待全部完成后再返回。
|
||||
|
||||
### 对比
|
||||
|
||||
| 方式 | 等待时间 | 体验 | 适用场景 |
|
||||
|------|----------|------|----------|
|
||||
| 普通请求 | 等待完整响应 | 一般 | 简单、快速的请求 |
|
||||
| 流式输出 | 实时看到生成过程 | ⭐ 优秀 | AI 生成、长文本 |
|
||||
|
||||
## 🚀 开始使用
|
||||
|
||||
### 前端:接收流式响应
|
||||
|
||||
```typescript
|
||||
import { WebsopyClient } from '@websopy/sdk'
|
||||
|
||||
const client = new WebsopyClient({
|
||||
apiKey: process.env.WEBSOPY_API_KEY
|
||||
})
|
||||
|
||||
async function streamChat() {
|
||||
const stream = await client.ai.chatStream({
|
||||
messages: [
|
||||
{ role: 'user', content: '写一篇关于 AI 的文章' }
|
||||
]
|
||||
})
|
||||
|
||||
// 方法 1:遍历数据块
|
||||
for await (const chunk of stream) {
|
||||
if (chunk.type === 'content') {
|
||||
process.stdout.write(chunk.content)
|
||||
}
|
||||
}
|
||||
|
||||
// 或方法 2:事件监听
|
||||
// stream.on('data', (chunk) => { ... })
|
||||
// stream.on('end', () => { ... })
|
||||
}
|
||||
```
|
||||
|
||||
### 响应数据结构
|
||||
|
||||
```typescript
|
||||
interface StreamChunk {
|
||||
type: 'content' | 'tool_call' | 'done' | 'error'
|
||||
content?: string
|
||||
tool?: {
|
||||
name: string
|
||||
arguments: string
|
||||
}
|
||||
usage?: {
|
||||
promptTokens: number
|
||||
completionTokens: number
|
||||
}
|
||||
}
|
||||
|
||||
// 示例数据块
|
||||
{ type: 'content', content: 'AI' }
|
||||
{ type: 'content', content: ' 正在' }
|
||||
{ type: 'content', content: '改变' }
|
||||
{ type: 'content', content: '世界...' }
|
||||
{ type: 'done', usage: { promptTokens: 20, completionTokens: 150 } }
|
||||
```
|
||||
|
||||
## 🌐 原生 SSE 实现
|
||||
|
||||
如果不用 SDK,直接使用 Fetch API:
|
||||
|
||||
### GET 请求
|
||||
|
||||
```typescript
|
||||
async function nativeStream() {
|
||||
const response = await fetch(
|
||||
'https://api.websopy.com/v1/ai/chat?message=Hello',
|
||||
{
|
||||
headers: {
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
'Accept': 'text/event-stream'
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const reader = response.body.getReader()
|
||||
const decoder = new TextDecoder()
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read()
|
||||
if (done) break
|
||||
|
||||
const chunk = decoder.decode(value)
|
||||
// 解析 SSE 数据
|
||||
const lines = chunk.split('\n')
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('data: ')) {
|
||||
const data = JSON.parse(line.slice(6))
|
||||
console.log('收到:', data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### POST 请求
|
||||
|
||||
```typescript
|
||||
async function streamPost() {
|
||||
const response = await fetch(
|
||||
'https://api.websopy.com/v1/ai/chat/stream',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'text/event-stream'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
messages: [
|
||||
{ role: 'user', content: '解释量子计算' }
|
||||
],
|
||||
model: 'gpt-4',
|
||||
stream: true
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
// 处理流...
|
||||
}
|
||||
```
|
||||
|
||||
## 🎨 前端组件示例
|
||||
|
||||
### React Hook
|
||||
|
||||
```typescript
|
||||
import { useState } from 'react'
|
||||
|
||||
function useStreamingChat() {
|
||||
const [messages, setMessages] = useState([])
|
||||
const [streaming, setStreaming] = useState(false)
|
||||
const [currentContent, setCurrentContent] = useState('')
|
||||
|
||||
const sendMessage = async (content) => {
|
||||
setStreaming(true)
|
||||
setCurrentContent('')
|
||||
|
||||
// 添加用户消息
|
||||
setMessages(prev => [...prev, { role: 'user', content }])
|
||||
|
||||
const stream = await client.ai.chatStream({
|
||||
messages: [...messages, { role: 'user', content }]
|
||||
})
|
||||
|
||||
for await (const chunk of stream) {
|
||||
if (chunk.type === 'content') {
|
||||
setCurrentContent(prev => prev + chunk.content)
|
||||
}
|
||||
}
|
||||
|
||||
// 保存完整消息
|
||||
setMessages(prev => [...prev, { role: 'assistant', content: currentContent }])
|
||||
setStreaming(false)
|
||||
}
|
||||
|
||||
return { messages, streaming, currentContent, sendMessage }
|
||||
}
|
||||
```
|
||||
|
||||
### Vue Composition API
|
||||
|
||||
```typescript
|
||||
import { ref } from 'vue'
|
||||
|
||||
export function useStreamingChat() {
|
||||
const messages = ref([])
|
||||
const streaming = ref(false)
|
||||
const currentContent = ref('')
|
||||
|
||||
const sendMessage = async (content) => {
|
||||
streaming.value = true
|
||||
currentContent.value = ''
|
||||
|
||||
messages.value.push({ role: 'user', content })
|
||||
|
||||
const stream = await client.ai.chatStream({
|
||||
messages: messages.value
|
||||
})
|
||||
|
||||
for await (const chunk of stream) {
|
||||
if (chunk.type === 'content') {
|
||||
currentContent.value += chunk.content
|
||||
}
|
||||
}
|
||||
|
||||
messages.value.push({ role: 'assistant', content: currentContent.value })
|
||||
streaming.value = false
|
||||
}
|
||||
|
||||
return { messages, streaming, currentContent, sendMessage }
|
||||
}
|
||||
```
|
||||
|
||||
## ⚙️ 服务端 SSE 配置
|
||||
|
||||
### Node.js Express
|
||||
|
||||
```typescript
|
||||
import express from 'express'
|
||||
|
||||
app.post('/api/chat/stream', async (req, res) => {
|
||||
// 设置 SSE 响应头
|
||||
res.setHeader('Content-Type', 'text/event-stream')
|
||||
res.setHeader('Cache-Control', 'no-cache')
|
||||
res.setHeader('Connection', 'keep-alive')
|
||||
|
||||
// 保持连接
|
||||
res.flushHeaders()
|
||||
|
||||
try {
|
||||
const stream = await client.ai.chatStream(req.body)
|
||||
|
||||
for await (const chunk of stream) {
|
||||
res.write(`data: ${JSON.stringify(chunk)}\n\n`)
|
||||
}
|
||||
|
||||
res.write('data: [DONE]\n\n')
|
||||
} catch (error) {
|
||||
res.write(`data: ${JSON.stringify({ error: error.message })}\n\n`)
|
||||
}
|
||||
|
||||
res.end()
|
||||
})
|
||||
```
|
||||
|
||||
### Next.js API Route
|
||||
|
||||
```typescript
|
||||
// app/api/chat/route.ts
|
||||
export async function POST(req: Request) {
|
||||
const encoder = new TextEncoder()
|
||||
const stream = new ReadableStream({
|
||||
async start(controller) {
|
||||
try {
|
||||
const stream = await client.ai.chatStream(await req.json())
|
||||
|
||||
for await (const chunk of stream) {
|
||||
controller.enqueue(
|
||||
encoder.encode(`data: ${JSON.stringify(chunk)}\n\n`)
|
||||
)
|
||||
}
|
||||
|
||||
controller.enqueue(encoder.encode('data: [DONE]\n\n'))
|
||||
} catch (error) {
|
||||
controller.enqueue(
|
||||
encoder.encode(`data: ${JSON.stringify({ error: error.message })}\n\n`)
|
||||
)
|
||||
}
|
||||
controller.close()
|
||||
}
|
||||
})
|
||||
|
||||
return new Response(stream, {
|
||||
headers: {
|
||||
'Content-Type': 'text/event-stream',
|
||||
'Cache-Control': 'no-cache',
|
||||
'Connection': 'keep-alive'
|
||||
}
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
## ❓ 常见问题
|
||||
|
||||
### Q: 流式中断怎么办?
|
||||
|
||||
```typescript
|
||||
async function streamWithReconnect() {
|
||||
const maxRetries = 3
|
||||
let retries = 0
|
||||
|
||||
while (retries < maxRetries) {
|
||||
try {
|
||||
const stream = await client.ai.chatStream({...})
|
||||
return stream
|
||||
} catch (error) {
|
||||
retries++
|
||||
await sleep(1000 * retries) // 指数退避
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Q: 如何在流式过程中取消请求?
|
||||
|
||||
```typescript
|
||||
const controller = new AbortController()
|
||||
|
||||
// 发送请求
|
||||
const stream = await client.ai.chatStream({
|
||||
messages: [...],
|
||||
signal: controller.signal
|
||||
})
|
||||
|
||||
// 取消请求
|
||||
controller.abort()
|
||||
```
|
||||
|
||||
### Q: SSE 和 WebSocket 区别?
|
||||
|
||||
| 特性 | SSE | WebSocket |
|
||||
|------|-----|-----------|
|
||||
| 方向 | 单向(服务端→客户端) | 双向 |
|
||||
| 协议 | HTTP | ws:// |
|
||||
| 重连 | 自动 | 需手动处理 |
|
||||
| 复杂度 | 简单 | 复杂 |
|
||||
| 适用 | AI 流式输出 | 实时聊天 |
|
||||
|
||||
---
|
||||
|
||||
**上一步:** [API Key 创建与管理](./apikey.md)
|
||||
**下一步:** [Webhook 事件接入](./webhook.md)
|
||||
259
public/docs/upgrade.md
Normal file
259
public/docs/upgrade.md
Normal file
@@ -0,0 +1,259 @@
|
||||
# 版本升级与回滚
|
||||
|
||||
> 平滑升级生产环境,数据库迁移方案,紧急回滚操作手册。
|
||||
|
||||
## ⚠️ 升级前必读
|
||||
|
||||
### 重要检查清单
|
||||
|
||||
- [ ] 备份数据库
|
||||
- [ ] 查阅版本更新日志
|
||||
- [ ] 在测试环境验证
|
||||
- [ ] 确认回滚方案
|
||||
- [ ] 通知相关人员
|
||||
- [ ] 选择低峰期执行
|
||||
|
||||
### 版本兼容性
|
||||
|
||||
| 当前版本 | 可直接升级到 |
|
||||
|----------|-------------|
|
||||
| 2.0.x | 2.1.x |
|
||||
| 2.1.x | 2.2.x, 2.3.x |
|
||||
| 2.2.x | 2.3.x |
|
||||
| 1.x | 需要先升级到 2.0 |
|
||||
|
||||
## 🚀 升级步骤
|
||||
|
||||
### 准备工作
|
||||
|
||||
```bash
|
||||
# 1. 进入部署目录
|
||||
cd ~/websopy-deploy
|
||||
|
||||
# 2. 备份当前版本配置
|
||||
cp docker-compose.yml docker-compose.yml.bak
|
||||
cp .env .env.bak
|
||||
|
||||
# 3. 备份数据库(必须!)
|
||||
docker-compose exec postgres pg_dump -U websopy > backups/db_backup_$(date +%Y%m%d).sql
|
||||
|
||||
# 4. 备份上传文件
|
||||
tar -czf backups/uploads_$(date +%Y%m%d).tar.gz -C /data/websopy uploads/
|
||||
```
|
||||
|
||||
### 执行升级
|
||||
|
||||
```bash
|
||||
# 1. 停止服务
|
||||
docker-compose down
|
||||
|
||||
# 2. 拉取新版本镜像
|
||||
docker-compose pull
|
||||
|
||||
# 3. 更新代码(如果使用 git 部署)
|
||||
git fetch origin
|
||||
git checkout v2.3.0
|
||||
|
||||
# 4. 检查新版本配置变更
|
||||
git diff v2.2.0 v2.3.0 -- .env.example
|
||||
|
||||
# 5. 合并配置变更
|
||||
nano .env
|
||||
|
||||
# 6. 启动服务
|
||||
docker-compose up -d
|
||||
|
||||
# 7. 执行数据库迁移
|
||||
docker-compose run --rm api websopy migrate
|
||||
```
|
||||
|
||||
### 验证升级
|
||||
|
||||
```bash
|
||||
# 检查服务状态
|
||||
docker-compose ps
|
||||
|
||||
# 检查 API 健康
|
||||
curl http://localhost:3000/api/health
|
||||
|
||||
# 检查版本号
|
||||
docker-compose exec api websopy --version
|
||||
|
||||
# 查看迁移日志
|
||||
docker-compose logs api | grep -i migrate
|
||||
```
|
||||
|
||||
## 🔧 数据库迁移
|
||||
|
||||
### 迁移说明
|
||||
|
||||
每个版本可能包含数据库迁移脚本,确保数据结构与代码兼容。
|
||||
|
||||
### 手动迁移
|
||||
|
||||
```bash
|
||||
# 查看待执行迁移
|
||||
docker-compose run --rm api websopy migrate:status
|
||||
|
||||
# 执行迁移
|
||||
docker-compose run --rm api websopy migrate
|
||||
|
||||
# 回滚上一个迁移
|
||||
docker-compose run --rm api websopy migrate:rollback
|
||||
```
|
||||
|
||||
### 迁移脚本结构
|
||||
|
||||
```bash
|
||||
migrations/
|
||||
├── 2024_01_15_000001_create_users.sql
|
||||
├── 2024_01_20_000002_add_avatar_to_users.sql
|
||||
└── 2024_02_01_000003_create_projects_table.sql
|
||||
```
|
||||
|
||||
## ⤵️ 紧急回滚
|
||||
|
||||
### 自动回滚
|
||||
|
||||
```bash
|
||||
# 如果启动失败,查看错误
|
||||
docker-compose logs api
|
||||
|
||||
# 回滚到上一个版本
|
||||
docker-compose down
|
||||
git checkout v2.2.0
|
||||
docker-compose pull
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### 恢复数据库
|
||||
|
||||
```bash
|
||||
# 停止服务
|
||||
docker-compose down
|
||||
|
||||
# 删除新数据库
|
||||
docker-compose exec postgres dropdb -U websopy websopy
|
||||
|
||||
# 创建空数据库
|
||||
docker-compose exec postgres createdb -U websopy websopy
|
||||
|
||||
# 恢复备份
|
||||
docker exec -i $(docker-compose ps -q postgres) psql -U websopy < backups/db_backup_20240115.sql
|
||||
|
||||
# 启动服务
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### 恢复文件
|
||||
|
||||
```bash
|
||||
# 恢复上传文件
|
||||
tar -xzf backups/uploads_20240115.tar.gz -C /data/websopy/
|
||||
```
|
||||
|
||||
## 📊 版本更新日志
|
||||
|
||||
### v2.3.0(最新)
|
||||
|
||||
**新增功能:**
|
||||
- 🚀 AI 流式输出优化,延迟降低 50%
|
||||
- 📊 新增数据看板组件
|
||||
- 🔔 支持自定义 Webhook 事件
|
||||
|
||||
**Breaking Changes:**
|
||||
- ⚠️ API `/ai/chat` 端点参数变更
|
||||
- ⚠️ 环境变量 `AI_MODEL` 重命名为 `DEFAULT_MODEL`
|
||||
|
||||
### v2.2.0
|
||||
|
||||
**新增功能:**
|
||||
- 💬 多语言支持
|
||||
- 📱 移动端优化
|
||||
- 🔐 SSO 单点登录
|
||||
|
||||
### v2.1.0
|
||||
|
||||
**新增功能:**
|
||||
- 🤖 AI Agent 功能
|
||||
- 📚 RAG 知识库
|
||||
- ⚡ 工作流自动化
|
||||
|
||||
## 🧪 测试环境验证
|
||||
|
||||
### 创建测试环境
|
||||
|
||||
```bash
|
||||
# 克隆生产配置到测试目录
|
||||
cp -r ~/websopy-deploy ~/websopy-test
|
||||
|
||||
# 修改配置
|
||||
cd ~/websopy-test
|
||||
nano .env
|
||||
# 修改端口避免冲突
|
||||
# WEBSOPY_PORT=3001
|
||||
|
||||
# 启动测试环境
|
||||
docker-compose up -d
|
||||
|
||||
# 使用测试数据
|
||||
docker-compose exec -T postgres psql -U websopy < test_data.sql
|
||||
```
|
||||
|
||||
### 测试清单
|
||||
|
||||
- [ ] 首页访问正常
|
||||
- [ ] 用户登录/注册
|
||||
- [ ] 主要功能操作
|
||||
- [ ] API 接口调用
|
||||
- [ ] Webhook 接收
|
||||
- [ ] 性能无明显下降
|
||||
|
||||
## ❓ 常见问题
|
||||
|
||||
### Q: 迁移失败怎么办?
|
||||
|
||||
1. 停止所有服务
|
||||
2. 恢复数据库备份
|
||||
3. 检查迁移脚本错误
|
||||
4. 联系技术支持
|
||||
|
||||
### Q: 升级后性能下降?
|
||||
|
||||
1. 检查资源使用情况
|
||||
2. 重启服务清理缓存
|
||||
3. 查看日志排查问题
|
||||
|
||||
### Q: 如何跳过测试直接升级?
|
||||
|
||||
不建议跳过测试。但如果必须:
|
||||
|
||||
```bash
|
||||
# 强制拉取最新镜像
|
||||
docker-compose pull --force
|
||||
|
||||
# 跳过测试启动
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
### Q: 镜像拉取失败?
|
||||
|
||||
```bash
|
||||
# 使用国内镜像源
|
||||
nano /etc/docker/daemon.json
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
|
||||
}
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo systemctl restart docker
|
||||
docker-compose pull
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**上一步:** [Docker Compose 部署](./docker.md)
|
||||
284
public/docs/webhook.md
Normal file
284
public/docs/webhook.md
Normal file
@@ -0,0 +1,284 @@
|
||||
# Webhook 事件接入
|
||||
|
||||
> 订阅业务事件,处理订单支付、AI 任务完成等异步通知。
|
||||
|
||||
## 🔔 什么是 Webhook?
|
||||
|
||||
Webhook 是一种「反向 API 调用」机制:
|
||||
|
||||
- 传统 API:你 → 平台(主动拉取)
|
||||
- Webhook:平台 → 你(被动接收)
|
||||
|
||||
当某个事件发生时(如支付成功),平台主动通知你的服务器。
|
||||
|
||||
## 📋 可订阅的事件
|
||||
|
||||
| 事件类型 | 说明 |
|
||||
|----------|------|
|
||||
| `payment.completed` | 支付完成 |
|
||||
| `payment.failed` | 支付失败 |
|
||||
| `subscription.created` | 订阅创建 |
|
||||
| `subscription.cancelled` | 订阅取消 |
|
||||
| `ai.task.completed` | AI 任务完成 |
|
||||
| `ai.task.failed` | AI 任务失败 |
|
||||
| `file.uploaded` | 文件上传完成 |
|
||||
| `project.created` | 项目创建 |
|
||||
| `user.invited` | 用户被邀请 |
|
||||
| `workflow.triggered` | 工作流触发 |
|
||||
|
||||
## 🚀 配置 Webhook
|
||||
|
||||
### 步骤 1:创建 Webhook 端点
|
||||
|
||||
在你的服务器创建一个 API 端点:
|
||||
|
||||
```typescript
|
||||
// Node.js Express 示例
|
||||
app.post('/webhook/websopy', express.raw({ type: 'application/json' }), (req, res) => {
|
||||
// 验证签名
|
||||
const signature = req.headers['x-websopy-signature']
|
||||
const timestamp = req.headers['x-websopy-timestamp']
|
||||
|
||||
if (!verifySignature(req.body, signature, timestamp)) {
|
||||
return res.status(401).send('Invalid signature')
|
||||
}
|
||||
|
||||
// 处理事件
|
||||
const event = JSON.parse(req.body)
|
||||
console.log('收到事件:', event.type)
|
||||
|
||||
// 立即返回 200(重要!)
|
||||
res.status(200).send('OK')
|
||||
|
||||
// 异步处理业务逻辑
|
||||
processEvent(event)
|
||||
})
|
||||
```
|
||||
|
||||
### 步骤 2:在控制台配置
|
||||
|
||||
1. 进入 **开发者中心 → Webhook**
|
||||
2. 点击 **添加端点**
|
||||
3. 填写配置:
|
||||
|
||||
| 配置项 | 说明 |
|
||||
|--------|------|
|
||||
| URL | 你的服务器地址,如 `https://your-server.com/webhook/websopy` |
|
||||
| 事件类型 | 选择要订阅的事件 |
|
||||
| 密钥 | 用于验证签名的密钥 |
|
||||
|
||||
### 步骤 3:验证签名
|
||||
|
||||
```typescript
|
||||
import crypto from 'crypto'
|
||||
|
||||
function verifySignature(body, signature, timestamp) {
|
||||
const secret = process.env.WEBSOPY_WEBHOOK_SECRET
|
||||
|
||||
// 检查时间戳(5分钟内有效)
|
||||
const ts = parseInt(timestamp)
|
||||
if (Date.now() - ts > 5 * 60 * 1000) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 计算签名
|
||||
const payload = `${timestamp}.${body}`
|
||||
const expectedSignature = crypto
|
||||
.createHmac('sha256', secret)
|
||||
.update(payload)
|
||||
.digest('hex')
|
||||
|
||||
return crypto.timingSafeEqual(
|
||||
Buffer.from(signature),
|
||||
Buffer.from(expectedSignature)
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## 📨 事件数据格式
|
||||
|
||||
### 通用结构
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "evt_abc123xyz",
|
||||
"type": "payment.completed",
|
||||
"created_at": "2024-01-15T10:30:00Z",
|
||||
"data": {
|
||||
// 事件相关数据
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 支付完成事件
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "evt_abc123xyz",
|
||||
"type": "payment.completed",
|
||||
"created_at": "2024-01-15T10:30:00Z",
|
||||
"data": {
|
||||
"order_id": "ord_xyz789",
|
||||
"amount": 29900,
|
||||
"currency": "CNY",
|
||||
"payment_method": "alipay",
|
||||
"status": "completed",
|
||||
"user_id": "user_123"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### AI 任务完成事件
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "evt_ai123",
|
||||
"type": "ai.task.completed",
|
||||
"created_at": "2024-01-15T10:30:00Z",
|
||||
"data": {
|
||||
"task_id": "task_abc",
|
||||
"task_type": "ai_chat",
|
||||
"result": {
|
||||
"content": "这里是 AI 的回复...",
|
||||
"model": "gpt-4",
|
||||
"usage": {
|
||||
"prompt_tokens": 50,
|
||||
"completion_tokens": 120
|
||||
}
|
||||
},
|
||||
"user_id": "user_123"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔧 处理业务逻辑
|
||||
|
||||
### 处理支付事件
|
||||
|
||||
```typescript
|
||||
async function processPaymentEvent(event) {
|
||||
const { order_id, amount, status } = event.data
|
||||
|
||||
switch (status) {
|
||||
case 'completed':
|
||||
// 1. 更新订单状态
|
||||
await updateOrderStatus(order_id, 'paid')
|
||||
|
||||
// 2. 发放权益
|
||||
await grantPremiumAccess(order_id)
|
||||
|
||||
// 3. 发送通知
|
||||
await sendConfirmationEmail(order_id)
|
||||
break
|
||||
|
||||
case 'failed':
|
||||
// 处理失败
|
||||
await handlePaymentFailure(order_id)
|
||||
break
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 处理 AI 任务事件
|
||||
|
||||
```typescript
|
||||
async function processAITaskEvent(event) {
|
||||
const { task_id, result, user_id } = event.data
|
||||
|
||||
// 保存 AI 回复
|
||||
await saveChatMessage({
|
||||
taskId: task_id,
|
||||
userId: user_id,
|
||||
content: result.content,
|
||||
model: result.model,
|
||||
tokens: result.usage.completion_tokens
|
||||
})
|
||||
|
||||
// 更新用户用量
|
||||
await updateUserUsage(user_id, result.usage)
|
||||
}
|
||||
```
|
||||
|
||||
## ⏰ 失败重试
|
||||
|
||||
如果你的服务器返回非 200 状态码,Websopy 会自动重试:
|
||||
|
||||
| 重试次数 | 延迟 |
|
||||
|----------|------|
|
||||
| 第 1 次 | 1 分钟 |
|
||||
| 第 2 次 | 5 分钟 |
|
||||
| 第 3 次 | 30 分钟 |
|
||||
| 第 4 次 | 2 小时 |
|
||||
| 第 5 次 | 12 小时 |
|
||||
|
||||
超过重试次数仍未成功,事件将被标记为失败,可在控制台手动重试。
|
||||
|
||||
### 幂等处理
|
||||
|
||||
```typescript
|
||||
const processedEvents = new Set()
|
||||
|
||||
app.post('/webhook/websopy', async (req, res) => {
|
||||
const event = JSON.parse(req.body)
|
||||
|
||||
// 幂等检查
|
||||
if (processedEvents.has(event.id)) {
|
||||
return res.status(200).send('Already processed')
|
||||
}
|
||||
|
||||
try {
|
||||
await processEvent(event)
|
||||
processedEvents.add(event.id)
|
||||
res.status(200).send('OK')
|
||||
} catch (error) {
|
||||
// 返回错误,触发重试
|
||||
res.status(500).send('Error')
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 🧪 本地开发测试
|
||||
|
||||
### 使用 ngrok
|
||||
|
||||
```bash
|
||||
# 安装 ngrok
|
||||
npm install -g ngrok
|
||||
|
||||
# 启动本地服务
|
||||
ngrok http 3000
|
||||
|
||||
# 复制输出的 https URL 到 Webhook 配置
|
||||
# https://abc123.ngrok.io/webhook/websopy
|
||||
```
|
||||
|
||||
### Webhook 测试工具
|
||||
|
||||
控制台提供「发送测试事件」功能,可以手动触发任意事件类型进行测试。
|
||||
|
||||
## ❓ 常见问题
|
||||
|
||||
### Q: 收到重复事件怎么办?
|
||||
|
||||
使用事件 ID 做幂等检查,参考上文示例。
|
||||
|
||||
### Q: 处理超时怎么办?
|
||||
|
||||
```typescript
|
||||
app.post('/webhook', async (req, res) => {
|
||||
// 立即返回
|
||||
res.status(200).send('OK')
|
||||
|
||||
// 异步处理
|
||||
setImmediate(() => processEvent(req.body)) // 使用 setImmediate 不阻塞
|
||||
})
|
||||
```
|
||||
|
||||
### Q: 如何查看 webhook 日志?
|
||||
|
||||
在控制台 → Webhook → 查看每个端点的请求历史和响应状态。
|
||||
|
||||
---
|
||||
|
||||
**上一步:** [流式输出(SSE)接入](./streaming.md)
|
||||
**下一步:** [REST API 完整参考](./api-reference.md)
|
||||
326
public/docs/workflow.md
Normal file
326
public/docs/workflow.md
Normal file
@@ -0,0 +1,326 @@
|
||||
# AI 工作流配置
|
||||
|
||||
> 使用 OpenClaw 工作流引擎,构建定时任务与自动化业务流。
|
||||
|
||||
## 🔄 什么是工作流?
|
||||
|
||||
工作流(Workflow)是预定义的一系列自动化步骤,可以:
|
||||
|
||||
- ⏰ **定时执行**:每天早上发送报表
|
||||
- 🔗 **事件触发**:用户注册后自动发送欢迎邮件
|
||||
- 🔁 **条件分支**:根据条件执行不同操作
|
||||
- 📊 **数据处理**:批量处理数据
|
||||
|
||||
## 🏗️ 核心概念
|
||||
|
||||
| 概念 | 说明 |
|
||||
|------|------|
|
||||
| **触发器 (Trigger)** | 工作流的启动条件 |
|
||||
| **节点 (Node)** | 工作流中的单个步骤 |
|
||||
| **连接 (Edge)** | 节点之间的数据流向 |
|
||||
| **变量 (Variable)** | 存储和传递数据 |
|
||||
| **执行日志** | 每次运行的记录 |
|
||||
|
||||
## 🚀 创建第一个工作流
|
||||
|
||||
### 方式一:代码定义
|
||||
|
||||
```typescript
|
||||
import { WorkflowBuilder } from '@websopy/ai-sdk'
|
||||
|
||||
const workflow = new WorkflowBuilder({
|
||||
name: '每日数据报告',
|
||||
description: '每天早上 9 点生成数据报告'
|
||||
})
|
||||
|
||||
// 添加触发器:定时执行
|
||||
workflow.addTrigger({
|
||||
type: 'schedule',
|
||||
config: {
|
||||
cron: '0 9 * * *', // 每天 9:00
|
||||
timezone: 'Asia/Shanghai'
|
||||
}
|
||||
})
|
||||
|
||||
// 添加节点:获取数据
|
||||
workflow.addNode('fetch-data', {
|
||||
type: 'http-request',
|
||||
config: {
|
||||
url: 'https://api.analytics.com/daily-stats',
|
||||
method: 'GET'
|
||||
}
|
||||
})
|
||||
|
||||
// 添加节点:生成报告
|
||||
workflow.addNode('generate-report', {
|
||||
type: 'ai-agent',
|
||||
config: {
|
||||
prompt: '根据以下数据生成日报:{{fetch-data.output}}'
|
||||
}
|
||||
})
|
||||
|
||||
// 添加节点:发送邮件
|
||||
workflow.addNode('send-email', {
|
||||
type: 'email',
|
||||
config: {
|
||||
to: ['team@company.com'],
|
||||
subject: '📊 每日数据报告',
|
||||
body: '{{generate-report.output}}'
|
||||
}
|
||||
})
|
||||
|
||||
// 节点连接
|
||||
workflow.connect('fetch-data', 'generate-report')
|
||||
workflow.connect('generate-report', 'send-email')
|
||||
|
||||
// 保存
|
||||
const created = await client.workflow.create(workflow.toJSON())
|
||||
console.log('工作流 ID:', created.id)
|
||||
```
|
||||
|
||||
### 方式二:可视化编辑器
|
||||
|
||||
在控制台 → AI 功能 → 工作流,点击「新建工作流」打开可视化编辑器。
|
||||
|
||||
## 📦 节点类型
|
||||
|
||||
### 1. HTTP 请求
|
||||
|
||||
```typescript
|
||||
workflow.addNode('call-api', {
|
||||
type: 'http-request',
|
||||
config: {
|
||||
url: 'https://api.example.com/data',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': 'Bearer xxx'
|
||||
},
|
||||
body: {
|
||||
query: 'SELECT * FROM orders'
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 2. AI 智能体
|
||||
|
||||
```typescript
|
||||
workflow.addNode('analyze', {
|
||||
type: 'ai-agent',
|
||||
config: {
|
||||
model: 'gpt-4',
|
||||
prompt: '分析以下数据,找出异常:{{input}}',
|
||||
temperature: 0.5
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 3. 条件分支
|
||||
|
||||
```typescript
|
||||
workflow.addNode('check-status', {
|
||||
type: 'condition',
|
||||
config: {
|
||||
conditions: [
|
||||
{
|
||||
expression: '{{input.amount}} > 10000',
|
||||
nextNode: 'high-value-handler'
|
||||
},
|
||||
{
|
||||
expression: '{{input.amount}} > 1000',
|
||||
nextNode: 'medium-handler'
|
||||
}
|
||||
],
|
||||
default: 'low-value-handler'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 4. 循环
|
||||
|
||||
```typescript
|
||||
workflow.addNode('process-items', {
|
||||
type: 'loop',
|
||||
config: {
|
||||
items: '{{batch-data.items}}',
|
||||
maxIterations: 100,
|
||||
// 循环体节点
|
||||
nodes: [...]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 5. 等待/延迟
|
||||
|
||||
```typescript
|
||||
workflow.addNode('delay', {
|
||||
type: 'delay',
|
||||
config: {
|
||||
duration: '24h' // 或 3600000(毫秒)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 6. Webhook
|
||||
|
||||
```typescript
|
||||
workflow.addNode('notify', {
|
||||
type: 'webhook',
|
||||
config: {
|
||||
url: 'https://your-server.com/webhook',
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: {
|
||||
event: 'workflow.completed',
|
||||
data: '{{workflow-output}}'
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 🔔 触发器类型
|
||||
|
||||
### 定时触发
|
||||
|
||||
```typescript
|
||||
workflow.addTrigger({
|
||||
type: 'schedule',
|
||||
config: {
|
||||
cron: '0 */4 * * *', // 每 4 小时
|
||||
// 或使用简单表达式
|
||||
interval: 'daily', // daily, weekly, monthly
|
||||
time: '09:00'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Webhook 触发
|
||||
|
||||
```typescript
|
||||
workflow.addTrigger({
|
||||
type: 'webhook',
|
||||
config: {
|
||||
// 创建后获得 webhook URL
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 事件触发
|
||||
|
||||
```typescript
|
||||
workflow.addTrigger({
|
||||
type: 'event',
|
||||
config: {
|
||||
events: [
|
||||
'user.created',
|
||||
'order.completed',
|
||||
'ai.task.failed'
|
||||
]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 🔧 变量与数据处理
|
||||
|
||||
### 定义变量
|
||||
|
||||
```typescript
|
||||
workflow.addNode('process', {
|
||||
type: 'transform',
|
||||
config: {
|
||||
variables: {
|
||||
totalAmount: '{{input.orders}} | sum("amount")',
|
||||
avgScore: '{{input.reviews}} | avg("score")',
|
||||
userNames: '{{input.users}} | map("name")'
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 数据转换
|
||||
|
||||
```typescript
|
||||
workflow.addNode('transform', {
|
||||
type: 'transform',
|
||||
config: {
|
||||
// 过滤器
|
||||
filter: '{{data}} | filter(item => item.active == true)',
|
||||
// 映射
|
||||
map: '{{data}} | map(item => ({ id: item.id, name: item.name }))',
|
||||
// 排序
|
||||
sort: '{{data}} | sortBy("created_at", "desc")'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## 📊 执行与监控
|
||||
|
||||
### 手动执行
|
||||
|
||||
```typescript
|
||||
// 立即执行一次
|
||||
const run = await client.workflow.run(workflowId, {
|
||||
input: {
|
||||
date: '2024-01-15'
|
||||
}
|
||||
})
|
||||
|
||||
console.log('执行 ID:', run.id)
|
||||
```
|
||||
|
||||
### 查看执行日志
|
||||
|
||||
```typescript
|
||||
const logs = await client.workflow.getRunLogs(run.id)
|
||||
|
||||
for (const log of logs) {
|
||||
console.log(`[${log.timestamp}] ${log.node}: ${log.status}`)
|
||||
if (log.error) {
|
||||
console.log(' 错误:', log.error)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 执行状态
|
||||
|
||||
```typescript
|
||||
const status = await client.workflow.getRunStatus(run.id)
|
||||
|
||||
console.log('状态:', status.status) // running, completed, failed
|
||||
console.log('当前节点:', status.currentNode)
|
||||
console.log('已用时间:', status.elapsedTime)
|
||||
```
|
||||
|
||||
## ❓ 常见问题
|
||||
|
||||
### Q: 工作流执行失败怎么办?
|
||||
|
||||
1. 查看执行日志定位问题节点
|
||||
2. 检查输入数据格式
|
||||
3. 查看节点配置是否正确
|
||||
4. 联系支持时提供执行 ID
|
||||
|
||||
### Q: 如何调试工作流?
|
||||
|
||||
使用「测试执行」功能,传入测试数据,逐步查看每个节点的输出。
|
||||
|
||||
### Q: 可以嵌套工作流吗?
|
||||
|
||||
是的,可以在一个工作流中调用另一个工作流:
|
||||
|
||||
```typescript
|
||||
workflow.addNode('sub-workflow', {
|
||||
type: 'workflow',
|
||||
config: {
|
||||
workflowId: 'wf-xxx',
|
||||
input: '{{current-data}}'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**上一步:** [RAG 知识库搭建](./rag.md)
|
||||
**下一步:** [Docker Compose 部署](./docker.md)
|
||||
Reference in New Issue
Block a user