@linkmind_claw/openclaw-faq-kb 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +91 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/api-client.d.ts +34 -0
- package/dist/lib/api-client.d.ts.map +1 -0
- package/dist/lib/api-client.js +91 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/tools/create-kb-and-train.d.ts +24 -0
- package/dist/tools/create-kb-and-train.d.ts.map +1 -0
- package/dist/tools/create-kb-and-train.js +74 -0
- package/dist/tools/create-kb-and-train.js.map +1 -0
- package/dist/tools/list-kb.d.ts +24 -0
- package/dist/tools/list-kb.d.ts.map +1 -0
- package/dist/tools/list-kb.js +101 -0
- package/dist/tools/list-kb.js.map +1 -0
- package/dist/tools/manage-faq.d.ts +28 -0
- package/dist/tools/manage-faq.d.ts.map +1 -0
- package/dist/tools/manage-faq.js +149 -0
- package/dist/tools/manage-faq.js.map +1 -0
- package/dist/tools/query-kb.d.ts +23 -0
- package/dist/tools/query-kb.d.ts.map +1 -0
- package/dist/tools/query-kb.js +48 -0
- package/dist/tools/query-kb.js.map +1 -0
- package/openclaw.plugin.json +31 -0
- package/package.json +33 -0
- package/skills/faq-kb/SKILL.md +124 -0
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# @linkmind_claw/openclaw-faq-kb
|
|
2
|
+
|
|
3
|
+
OpenClaw Plugin — FAQ Knowledge Base: one-click document training & intelligent Q&A.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
openclaw plugins install @linkmind_claw/openclaw-faq-kb
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or install from npm directly:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @linkmind_claw/openclaw-faq-kb
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Configuration
|
|
18
|
+
|
|
19
|
+
In your OpenClaw config, set:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"faq-knowledge-base": {
|
|
24
|
+
"apiBaseUrl": "http://67.212.146.21:8999",
|
|
25
|
+
"apiToken": ""
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
| Field | Default | Description |
|
|
31
|
+
|-------|---------|-------------|
|
|
32
|
+
| `apiBaseUrl` | `http://67.212.146.21:8999` | FAQ KB API server address |
|
|
33
|
+
| `apiToken` | (empty = auto-acquire) | Static API token, or leave empty for auto-renewal |
|
|
34
|
+
| `pollIntervalMs` | `8000` | Pipeline progress poll interval (ms) |
|
|
35
|
+
| `pipelineTimeoutMs` | `1200000` | Pipeline timeout (ms), default 20 min |
|
|
36
|
+
|
|
37
|
+
## Tools Provided
|
|
38
|
+
|
|
39
|
+
| Tool | Description |
|
|
40
|
+
|------|-------------|
|
|
41
|
+
| `faq_kb_create_and_train` | Create a knowledge base + upload document + full auto-pipeline training |
|
|
42
|
+
| `faq_kb_query` | Ask a question against a trained knowledge base |
|
|
43
|
+
| `faq_kb_manage` | FAQ CRUD: create, update, delete, list, get |
|
|
44
|
+
| `faq_kb_list` | Knowledge base management: list, detail, delete, system status |
|
|
45
|
+
|
|
46
|
+
## Development
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install
|
|
50
|
+
npm run build
|
|
51
|
+
npm test
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Publishing
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npm run build
|
|
58
|
+
npm publish --access public
|
|
59
|
+
# or
|
|
60
|
+
clawhub publish
|
|
61
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw Plugin entry — FAQ Knowledge Base
|
|
3
|
+
*
|
|
4
|
+
* Registers four agent tools that wrap the 8999 FAQ KB API into
|
|
5
|
+
* high-level workflow operations:
|
|
6
|
+
*
|
|
7
|
+
* 1. faq_kb_create_and_train — one-click: create KB + auto-pipeline
|
|
8
|
+
* 2. faq_kb_query — intelligent Q&A
|
|
9
|
+
* 3. faq_kb_manage — FAQ CRUD
|
|
10
|
+
* 4. faq_kb_list — KB inventory & system status
|
|
11
|
+
*/
|
|
12
|
+
interface PluginConfig {
|
|
13
|
+
apiBaseUrl?: string;
|
|
14
|
+
apiToken?: string;
|
|
15
|
+
pollIntervalMs?: number;
|
|
16
|
+
pipelineTimeoutMs?: number;
|
|
17
|
+
}
|
|
18
|
+
interface ToolResult {
|
|
19
|
+
content: Array<{
|
|
20
|
+
type: "text";
|
|
21
|
+
text: string;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
24
|
+
interface ToolDef<P> {
|
|
25
|
+
name: string;
|
|
26
|
+
label?: string;
|
|
27
|
+
description: string;
|
|
28
|
+
parameters: unknown;
|
|
29
|
+
execute: (toolCallId: string, params: P) => Promise<ToolResult>;
|
|
30
|
+
}
|
|
31
|
+
interface PluginApi {
|
|
32
|
+
getConfig: () => PluginConfig;
|
|
33
|
+
registerTool: <P>(def: ToolDef<P>) => void;
|
|
34
|
+
}
|
|
35
|
+
interface PluginEntry {
|
|
36
|
+
id: string;
|
|
37
|
+
name: string;
|
|
38
|
+
description: string;
|
|
39
|
+
register: (api: PluginApi) => void;
|
|
40
|
+
}
|
|
41
|
+
declare const _default: PluginEntry;
|
|
42
|
+
export default _default;
|
|
43
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA+BH,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAOD,UAAU,UAAU;IAClB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAED,UAAU,OAAO,CAAC,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CACjE;AAED,UAAU,SAAS;IACjB,SAAS,EAAE,MAAM,YAAY,CAAC;IAC9B,YAAY,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;CAC5C;AAED,UAAU,WAAW;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,IAAI,CAAC;CACpC;;AAQD,wBAiFG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenClaw Plugin entry — FAQ Knowledge Base
|
|
3
|
+
*
|
|
4
|
+
* Registers four agent tools that wrap the 8999 FAQ KB API into
|
|
5
|
+
* high-level workflow operations:
|
|
6
|
+
*
|
|
7
|
+
* 1. faq_kb_create_and_train — one-click: create KB + auto-pipeline
|
|
8
|
+
* 2. faq_kb_query — intelligent Q&A
|
|
9
|
+
* 3. faq_kb_manage — FAQ CRUD
|
|
10
|
+
* 4. faq_kb_list — KB inventory & system status
|
|
11
|
+
*/
|
|
12
|
+
import { FaqKbApiClient } from "./lib/api-client.js";
|
|
13
|
+
import { CreateAndTrainParams, executeCreateAndTrain, } from "./tools/create-kb-and-train.js";
|
|
14
|
+
import { QueryParams, executeQuery, } from "./tools/query-kb.js";
|
|
15
|
+
import { ManageFaqParams, executeManageFaq, } from "./tools/manage-faq.js";
|
|
16
|
+
import { ListKbParams, executeListKb, } from "./tools/list-kb.js";
|
|
17
|
+
function definePluginEntry(entry) {
|
|
18
|
+
return entry;
|
|
19
|
+
}
|
|
20
|
+
// ── Export ─────────────────────────────────────────────────────────────
|
|
21
|
+
export default definePluginEntry({
|
|
22
|
+
id: "faq-knowledge-base",
|
|
23
|
+
name: "FAQ Knowledge Base",
|
|
24
|
+
description: "FAQ 知识库插件:一键上传文档训练知识库,智能问答,FAQ 增删改查",
|
|
25
|
+
register(api) {
|
|
26
|
+
const cfg = api.getConfig();
|
|
27
|
+
const baseUrl = cfg.apiBaseUrl || "http://67.212.146.21:8999";
|
|
28
|
+
const pollInterval = cfg.pollIntervalMs ?? 8_000;
|
|
29
|
+
const pipelineTimeout = cfg.pipelineTimeoutMs ?? 20 * 60 * 1000;
|
|
30
|
+
const client = new FaqKbApiClient({
|
|
31
|
+
baseUrl,
|
|
32
|
+
staticToken: cfg.apiToken || undefined,
|
|
33
|
+
});
|
|
34
|
+
// ── Tool 1: Create & Train ────────────────────────────────────────
|
|
35
|
+
api.registerTool({
|
|
36
|
+
name: "faq_kb_create_and_train",
|
|
37
|
+
label: "创建知识库并训练",
|
|
38
|
+
description: [
|
|
39
|
+
"创建一个新的 FAQ 知识库并自动完成全部训练流程。",
|
|
40
|
+
"内部执行: 创建知识库 → 上传文档 → AI 提取 FAQ → 构建知识树 → 建索引。",
|
|
41
|
+
"训练完成后知识库即可用于问答(faq_kb_query)。",
|
|
42
|
+
"支持 PDF / DOCX / DOC / TXT / MD 格式,通过 file_url 传入文件地址。",
|
|
43
|
+
"训练过程通常需要 2-10 分钟,取决于文档大小。",
|
|
44
|
+
].join(" "),
|
|
45
|
+
parameters: CreateAndTrainParams,
|
|
46
|
+
execute: (_id, params) => executeCreateAndTrain(client, params, pollInterval, pipelineTimeout),
|
|
47
|
+
});
|
|
48
|
+
// ── Tool 2: Query ─────────────────────────────────────────────────
|
|
49
|
+
api.registerTool({
|
|
50
|
+
name: "faq_kb_query",
|
|
51
|
+
label: "知识库问答",
|
|
52
|
+
description: [
|
|
53
|
+
"向指定知识库提问并获取 AI 智能回答。",
|
|
54
|
+
"知识库必须已经训练完成(is_active=true)。",
|
|
55
|
+
"设置 enable_polish=true 可让 LLM 综合多个 FAQ 生成更自然的回答。",
|
|
56
|
+
"返回包含答案、置信度、来源引用和日志 ID。",
|
|
57
|
+
].join(" "),
|
|
58
|
+
parameters: QueryParams,
|
|
59
|
+
execute: (_id, params) => executeQuery(client, params),
|
|
60
|
+
});
|
|
61
|
+
// ── Tool 3: Manage FAQ ────────────────────────────────────────────
|
|
62
|
+
api.registerTool({
|
|
63
|
+
name: "faq_kb_manage",
|
|
64
|
+
label: "FAQ 管理",
|
|
65
|
+
description: [
|
|
66
|
+
"管理知识库中的 FAQ(问答对): 创建、更新、删除、列表、详情。",
|
|
67
|
+
"通过 action 参数指定操作类型。",
|
|
68
|
+
"create/update 需要 question 和 answer;",
|
|
69
|
+
"update/delete/get 需要 faq_id;",
|
|
70
|
+
"list 支持 keyword 搜索和分页。",
|
|
71
|
+
].join(" "),
|
|
72
|
+
parameters: ManageFaqParams,
|
|
73
|
+
execute: (_id, params) => executeManageFaq(client, params),
|
|
74
|
+
});
|
|
75
|
+
// ── Tool 4: List KB ───────────────────────────────────────────────
|
|
76
|
+
api.registerTool({
|
|
77
|
+
name: "faq_kb_list",
|
|
78
|
+
label: "知识库管理",
|
|
79
|
+
description: [
|
|
80
|
+
"查询和管理知识库: 列出全部知识库、查看详情、删除知识库、查看系统状态。",
|
|
81
|
+
"list: 列出所有知识库,支持按名称和标签筛选;",
|
|
82
|
+
"detail: 查看知识库详情(需要 kb_id);",
|
|
83
|
+
"delete: 删除知识库(需要 kb_id);",
|
|
84
|
+
"system_status: 查看后端系统状态。",
|
|
85
|
+
].join(" "),
|
|
86
|
+
parameters: ListKbParams,
|
|
87
|
+
execute: (_id, params) => executeListKb(client, params),
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the FAQ Knowledge Base API (port 8999).
|
|
3
|
+
*
|
|
4
|
+
* Handles automatic token acquisition and renewal so that every
|
|
5
|
+
* outgoing request carries a valid `X-API-Token` header.
|
|
6
|
+
*/
|
|
7
|
+
export interface ApiClientConfig {
|
|
8
|
+
baseUrl: string;
|
|
9
|
+
/** If provided, skip auto-token and use this static token. */
|
|
10
|
+
staticToken?: string;
|
|
11
|
+
/** Request timeout in ms (default 30 000). */
|
|
12
|
+
timeoutMs?: number;
|
|
13
|
+
}
|
|
14
|
+
export declare class FaqKbApiClient {
|
|
15
|
+
private readonly baseUrl;
|
|
16
|
+
private readonly staticToken;
|
|
17
|
+
private readonly timeoutMs;
|
|
18
|
+
private tokenCache;
|
|
19
|
+
constructor(cfg: ApiClientConfig);
|
|
20
|
+
private acquireToken;
|
|
21
|
+
private getToken;
|
|
22
|
+
request<T = unknown>(method: string, path: string, body?: unknown): Promise<T>;
|
|
23
|
+
get<T = unknown>(path: string): Promise<T>;
|
|
24
|
+
post<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
25
|
+
put<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
26
|
+
del<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
27
|
+
patch<T = unknown>(path: string, body?: unknown): Promise<T>;
|
|
28
|
+
}
|
|
29
|
+
export interface ApiResponse<D = Record<string, unknown>> {
|
|
30
|
+
success: boolean;
|
|
31
|
+
message: string;
|
|
32
|
+
data: D;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../lib/api-client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAOD,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,UAAU,CAA2B;gBAEjC,GAAG,EAAE,eAAe;YAQlB,YAAY;YAqBZ,QAAQ;IAUhB,OAAO,CAAC,CAAC,GAAG,OAAO,EACvB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,GACb,OAAO,CAAC,CAAC,CAAC;IAqCb,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM;IAI7B,IAAI,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;IAI9C,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;IAI7C,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;IAI7C,KAAK,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;CAGhD;AAID,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACtD,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,CAAC,CAAC;CACT"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for the FAQ Knowledge Base API (port 8999).
|
|
3
|
+
*
|
|
4
|
+
* Handles automatic token acquisition and renewal so that every
|
|
5
|
+
* outgoing request carries a valid `X-API-Token` header.
|
|
6
|
+
*/
|
|
7
|
+
export class FaqKbApiClient {
|
|
8
|
+
baseUrl;
|
|
9
|
+
staticToken;
|
|
10
|
+
timeoutMs;
|
|
11
|
+
tokenCache = null;
|
|
12
|
+
constructor(cfg) {
|
|
13
|
+
this.baseUrl = cfg.baseUrl.replace(/\/+$/, "");
|
|
14
|
+
this.staticToken = cfg.staticToken || undefined;
|
|
15
|
+
this.timeoutMs = cfg.timeoutMs ?? 30_000;
|
|
16
|
+
}
|
|
17
|
+
// ── Token management ────────────────────────────────────────────────
|
|
18
|
+
async acquireToken() {
|
|
19
|
+
const res = await fetch(`${this.baseUrl}/api/token`, {
|
|
20
|
+
method: "POST",
|
|
21
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
22
|
+
});
|
|
23
|
+
if (!res.ok) {
|
|
24
|
+
throw new Error(`Token acquisition failed: ${res.status} ${res.statusText}`);
|
|
25
|
+
}
|
|
26
|
+
const body = (await res.json());
|
|
27
|
+
// Renew 5 min before actual expiry to avoid edge-case failures
|
|
28
|
+
const safetyMarginMs = 5 * 60 * 1000;
|
|
29
|
+
this.tokenCache = {
|
|
30
|
+
token: body.token,
|
|
31
|
+
expiresAt: Date.now() + body.expires_in * 1000 - safetyMarginMs,
|
|
32
|
+
};
|
|
33
|
+
return body.token;
|
|
34
|
+
}
|
|
35
|
+
async getToken() {
|
|
36
|
+
if (this.staticToken)
|
|
37
|
+
return this.staticToken;
|
|
38
|
+
if (this.tokenCache && Date.now() < this.tokenCache.expiresAt) {
|
|
39
|
+
return this.tokenCache.token;
|
|
40
|
+
}
|
|
41
|
+
return this.acquireToken();
|
|
42
|
+
}
|
|
43
|
+
// ── Generic request ─────────────────────────────────────────────────
|
|
44
|
+
async request(method, path, body) {
|
|
45
|
+
const token = await this.getToken();
|
|
46
|
+
const url = `${this.baseUrl}${path}`;
|
|
47
|
+
const headers = {
|
|
48
|
+
"X-API-Token": token,
|
|
49
|
+
Accept: "application/json",
|
|
50
|
+
};
|
|
51
|
+
const init = {
|
|
52
|
+
method,
|
|
53
|
+
headers,
|
|
54
|
+
signal: AbortSignal.timeout(this.timeoutMs),
|
|
55
|
+
};
|
|
56
|
+
if (body !== undefined) {
|
|
57
|
+
headers["Content-Type"] = "application/json";
|
|
58
|
+
init.body = JSON.stringify(body);
|
|
59
|
+
}
|
|
60
|
+
const res = await fetch(url, init);
|
|
61
|
+
if (!res.ok) {
|
|
62
|
+
let detail;
|
|
63
|
+
try {
|
|
64
|
+
const err = await res.json();
|
|
65
|
+
detail = err.detail ?? JSON.stringify(err);
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
detail = await res.text();
|
|
69
|
+
}
|
|
70
|
+
throw new Error(`API ${method} ${path} → ${res.status}: ${detail}`);
|
|
71
|
+
}
|
|
72
|
+
return res.json();
|
|
73
|
+
}
|
|
74
|
+
// ── Convenience wrappers ────────────────────────────────────────────
|
|
75
|
+
get(path) {
|
|
76
|
+
return this.request("GET", path);
|
|
77
|
+
}
|
|
78
|
+
post(path, body) {
|
|
79
|
+
return this.request("POST", path, body);
|
|
80
|
+
}
|
|
81
|
+
put(path, body) {
|
|
82
|
+
return this.request("PUT", path, body);
|
|
83
|
+
}
|
|
84
|
+
del(path, body) {
|
|
85
|
+
return this.request("DELETE", path, body);
|
|
86
|
+
}
|
|
87
|
+
patch(path, body) {
|
|
88
|
+
return this.request("PATCH", path, body);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../lib/api-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool 1 — faq_kb_create_and_train
|
|
3
|
+
*
|
|
4
|
+
* One-shot workflow: create a knowledge base, upload a document, and run
|
|
5
|
+
* the full auto-pipeline (AI extract -> build tree -> confirm -> index).
|
|
6
|
+
* The tool polls progress internally and only returns when the pipeline
|
|
7
|
+
* completes (or fails / times out).
|
|
8
|
+
*/
|
|
9
|
+
import { type Static } from "@sinclair/typebox";
|
|
10
|
+
import type { FaqKbApiClient } from "../lib/api-client.js";
|
|
11
|
+
export declare const CreateAndTrainParams: import("@sinclair/typebox").TObject<{
|
|
12
|
+
kb_name: import("@sinclair/typebox").TString;
|
|
13
|
+
file_url: import("@sinclair/typebox").TString;
|
|
14
|
+
description: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
15
|
+
tag_name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
16
|
+
}>;
|
|
17
|
+
export type CreateAndTrainInput = Static<typeof CreateAndTrainParams>;
|
|
18
|
+
export declare function executeCreateAndTrain(client: FaqKbApiClient, params: CreateAndTrainInput, pollIntervalMs: number, pipelineTimeoutMs: number): Promise<{
|
|
19
|
+
content: {
|
|
20
|
+
type: "text";
|
|
21
|
+
text: string;
|
|
22
|
+
}[];
|
|
23
|
+
}>;
|
|
24
|
+
//# sourceMappingURL=create-kb-and-train.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-kb-and-train.d.ts","sourceRoot":"","sources":["../../tools/create-kb-and-train.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,sBAAsB,CAAC;AAIxE,eAAO,MAAM,oBAAoB;;;;;EAW/B,CAAC;AAEH,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAmBtE,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,mBAAmB,EAC3B,cAAc,EAAE,MAAM,EACtB,iBAAiB,EAAE,MAAM;;;;;GA0E1B"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool 1 — faq_kb_create_and_train
|
|
3
|
+
*
|
|
4
|
+
* One-shot workflow: create a knowledge base, upload a document, and run
|
|
5
|
+
* the full auto-pipeline (AI extract -> build tree -> confirm -> index).
|
|
6
|
+
* The tool polls progress internally and only returns when the pipeline
|
|
7
|
+
* completes (or fails / times out).
|
|
8
|
+
*/
|
|
9
|
+
import { Type } from "@sinclair/typebox";
|
|
10
|
+
// ── Parameter schema ──────────────────────────────────────────────────
|
|
11
|
+
export const CreateAndTrainParams = Type.Object({
|
|
12
|
+
kb_name: Type.String({ description: "知识库名称" }),
|
|
13
|
+
file_url: Type.String({
|
|
14
|
+
description: "文档文件的 URL 地址(支持 PDF / DOCX / DOC / TXT / MD)",
|
|
15
|
+
}),
|
|
16
|
+
description: Type.Optional(Type.String({ description: "知识库描述(可选)" })),
|
|
17
|
+
tag_name: Type.Optional(Type.String({ description: "知识库标签,用于分类(可选)" })),
|
|
18
|
+
});
|
|
19
|
+
// ── Execute ───────────────────────────────────────────────────────────
|
|
20
|
+
export async function executeCreateAndTrain(client, params, pollIntervalMs, pipelineTimeoutMs) {
|
|
21
|
+
// Step 1 — Create knowledge base
|
|
22
|
+
const kbRes = await client.post("/knowledge_bases", {
|
|
23
|
+
name: params.kb_name,
|
|
24
|
+
description: params.description ?? "",
|
|
25
|
+
tag_name: params.tag_name ?? null,
|
|
26
|
+
});
|
|
27
|
+
const kbId = kbRes.id;
|
|
28
|
+
// Step 2 — Start auto-pipeline
|
|
29
|
+
const pipeRes = await client.post(`/knowledge_bases/${kbId}/auto_pipeline`, {
|
|
30
|
+
name: params.kb_name,
|
|
31
|
+
description: params.description ?? "",
|
|
32
|
+
file_path: params.file_url,
|
|
33
|
+
});
|
|
34
|
+
if (!pipeRes.success) {
|
|
35
|
+
return textResult(`[ERROR] 启动全自动管线失败: ${pipeRes.message}(kb_id=${kbId})`);
|
|
36
|
+
}
|
|
37
|
+
const taskId = pipeRes.data.task_id;
|
|
38
|
+
// Step 3 — Poll until completed / failed / timeout
|
|
39
|
+
const deadline = Date.now() + pipelineTimeoutMs;
|
|
40
|
+
let last = null;
|
|
41
|
+
while (Date.now() < deadline) {
|
|
42
|
+
await sleep(pollIntervalMs);
|
|
43
|
+
const prog = await client.get(`/knowledge_bases/${kbId}/auto_pipeline/${taskId}`);
|
|
44
|
+
if (!prog.success)
|
|
45
|
+
continue;
|
|
46
|
+
last = prog.data;
|
|
47
|
+
if (last.stage === "completed") {
|
|
48
|
+
return textResult([
|
|
49
|
+
`知识库创建并训练完成!`,
|
|
50
|
+
` kb_id : ${kbId}`,
|
|
51
|
+
` 知识库名称 : ${params.kb_name}`,
|
|
52
|
+
` FAQ 数量 : ${last.faq_count}`,
|
|
53
|
+
` 节点数量 : ${last.node_count}`,
|
|
54
|
+
` 状态 : 就绪,可以使用 faq_kb_query 工具进行问答`,
|
|
55
|
+
].join("\n"));
|
|
56
|
+
}
|
|
57
|
+
if (last.stage === "failed") {
|
|
58
|
+
return textResult(`[ERROR] 管线失败: ${last.error ?? "未知错误"}(kb_id=${kbId}, task_id=${taskId})`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Timeout
|
|
62
|
+
const stageInfo = last
|
|
63
|
+
? `当前阶段=${last.stage_label}, 进度=${last.progress}%`
|
|
64
|
+
: "无进度信息";
|
|
65
|
+
return textResult(`[TIMEOUT] 全自动管线超时(${pipelineTimeoutMs / 1000}s)。${stageInfo}。kb_id=${kbId}, task_id=${taskId}`);
|
|
66
|
+
}
|
|
67
|
+
// ── Helpers ───────────────────────────────────────────────────────────
|
|
68
|
+
function sleep(ms) {
|
|
69
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
70
|
+
}
|
|
71
|
+
function textResult(text) {
|
|
72
|
+
return { content: [{ type: "text", text }] };
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=create-kb-and-train.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-kb-and-train.js","sourceRoot":"","sources":["../../tools/create-kb-and-train.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool 4 — faq_kb_list
|
|
3
|
+
*
|
|
4
|
+
* Query knowledge base inventory: list all, get detail, check training
|
|
5
|
+
* status, or retrieve system status.
|
|
6
|
+
*/
|
|
7
|
+
import { type Static } from "@sinclair/typebox";
|
|
8
|
+
import type { FaqKbApiClient } from "../lib/api-client.js";
|
|
9
|
+
export declare const ListKbParams: import("@sinclair/typebox").TObject<{
|
|
10
|
+
action: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"list">, import("@sinclair/typebox").TLiteral<"detail">, import("@sinclair/typebox").TLiteral<"delete">, import("@sinclair/typebox").TLiteral<"system_status">]>;
|
|
11
|
+
kb_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
12
|
+
keyword: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
13
|
+
tag_name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
14
|
+
page: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
15
|
+
page_size: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
16
|
+
}>;
|
|
17
|
+
export type ListKbInput = Static<typeof ListKbParams>;
|
|
18
|
+
export declare function executeListKb(client: FaqKbApiClient, params: ListKbInput): Promise<{
|
|
19
|
+
content: {
|
|
20
|
+
type: "text";
|
|
21
|
+
text: string;
|
|
22
|
+
}[];
|
|
23
|
+
}>;
|
|
24
|
+
//# sourceMappingURL=list-kb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-kb.d.ts","sourceRoot":"","sources":["../../tools/list-kb.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,sBAAsB,CAAC;AAExE,eAAO,MAAM,YAAY;;;;;;;EAwBvB,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,YAAY,CAAC,CAAC;AAEtD,wBAAsB,aAAa,CACjC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,WAAW;;;;;GAcpB"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool 4 — faq_kb_list
|
|
3
|
+
*
|
|
4
|
+
* Query knowledge base inventory: list all, get detail, check training
|
|
5
|
+
* status, or retrieve system status.
|
|
6
|
+
*/
|
|
7
|
+
import { Type } from "@sinclair/typebox";
|
|
8
|
+
export const ListKbParams = Type.Object({
|
|
9
|
+
action: Type.Union([
|
|
10
|
+
Type.Literal("list"),
|
|
11
|
+
Type.Literal("detail"),
|
|
12
|
+
Type.Literal("delete"),
|
|
13
|
+
Type.Literal("system_status"),
|
|
14
|
+
], {
|
|
15
|
+
description: "操作类型: list=列出所有知识库, detail=知识库详情, delete=删除知识库, system_status=系统状态",
|
|
16
|
+
}),
|
|
17
|
+
kb_id: Type.Optional(Type.String({ description: "知识库 ID(detail / delete 时必填)" })),
|
|
18
|
+
keyword: Type.Optional(Type.String({ description: "按名称搜索(list 时可选)" })),
|
|
19
|
+
tag_name: Type.Optional(Type.String({ description: "按标签筛选(list 时可选)" })),
|
|
20
|
+
page: Type.Optional(Type.Number({ description: "页码(默认 1)" })),
|
|
21
|
+
page_size: Type.Optional(Type.Number({ description: "每页大小(默认 0=全部)" })),
|
|
22
|
+
});
|
|
23
|
+
export async function executeListKb(client, params) {
|
|
24
|
+
switch (params.action) {
|
|
25
|
+
case "list":
|
|
26
|
+
return doList(client, params);
|
|
27
|
+
case "detail":
|
|
28
|
+
return doDetail(client, params);
|
|
29
|
+
case "delete":
|
|
30
|
+
return doDelete(client, params);
|
|
31
|
+
case "system_status":
|
|
32
|
+
return doSystemStatus(client);
|
|
33
|
+
default:
|
|
34
|
+
return textResult(`[ERROR] 不支持的 action: ${params.action}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
async function doList(client, p) {
|
|
38
|
+
const qp = new URLSearchParams();
|
|
39
|
+
if (p.keyword)
|
|
40
|
+
qp.set("keyword", p.keyword);
|
|
41
|
+
if (p.tag_name)
|
|
42
|
+
qp.set("tag_name", p.tag_name);
|
|
43
|
+
qp.set("page", String(p.page ?? 1));
|
|
44
|
+
qp.set("page_size", String(p.page_size ?? 0));
|
|
45
|
+
const res = await client.get(`/knowledge_bases?${qp.toString()}`);
|
|
46
|
+
const items = res.items ?? res.data?.items ?? [];
|
|
47
|
+
const total = res.total ?? items.length;
|
|
48
|
+
const lines = [`知识库列表(共 ${total} 个):`];
|
|
49
|
+
for (const kb of items) {
|
|
50
|
+
const status = kb.is_active ? "就绪" : "未训练";
|
|
51
|
+
const tag = kb.tag_name ? ` [${kb.tag_name}]` : "";
|
|
52
|
+
lines.push(` ${kb.id} ${kb.name}${tag} (${status})`);
|
|
53
|
+
}
|
|
54
|
+
if (items.length === 0) {
|
|
55
|
+
lines.push(" (无知识库)");
|
|
56
|
+
}
|
|
57
|
+
return textResult(lines.join("\n"));
|
|
58
|
+
}
|
|
59
|
+
// ── Detail ────────────────────────────────────────────────────────────
|
|
60
|
+
async function doDetail(client, p) {
|
|
61
|
+
if (!p.kb_id) {
|
|
62
|
+
return textResult("[ERROR] 查看知识库详情需要提供 kb_id");
|
|
63
|
+
}
|
|
64
|
+
const res = await client.get(`/knowledge_bases/${p.kb_id}`);
|
|
65
|
+
const kb = res;
|
|
66
|
+
const createdDate = new Date(kb.created_at).toLocaleString("zh-CN");
|
|
67
|
+
const trainDate = kb.trainover_at
|
|
68
|
+
? new Date(kb.trainover_at).toLocaleString("zh-CN")
|
|
69
|
+
: "未训练";
|
|
70
|
+
return textResult([
|
|
71
|
+
`知识库详情:`,
|
|
72
|
+
` ID : ${kb.id}`,
|
|
73
|
+
` 名称 : ${kb.name}`,
|
|
74
|
+
` 描述 : ${kb.description ?? "(无)"}`,
|
|
75
|
+
` 标签 : ${kb.tag_name ?? "(无)"}`,
|
|
76
|
+
` 状态 : ${kb.is_active ? "就绪(可问答)" : "未训练"}`,
|
|
77
|
+
` 创建时间 : ${createdDate}`,
|
|
78
|
+
` 训练完成时间: ${trainDate}`,
|
|
79
|
+
].join("\n"));
|
|
80
|
+
}
|
|
81
|
+
// ── Delete ────────────────────────────────────────────────────────────
|
|
82
|
+
async function doDelete(client, p) {
|
|
83
|
+
if (!p.kb_id) {
|
|
84
|
+
return textResult("[ERROR] 删除知识库需要提供 kb_id");
|
|
85
|
+
}
|
|
86
|
+
const res = await client.del(`/knowledge_bases/${p.kb_id}`);
|
|
87
|
+
return textResult(`知识库删除成功! kb_id=${p.kb_id}\n${res.message ?? ""}`);
|
|
88
|
+
}
|
|
89
|
+
// ── System status ─────────────────────────────────────────────────────
|
|
90
|
+
async function doSystemStatus(client) {
|
|
91
|
+
const res = await client.get("/system/status");
|
|
92
|
+
if (!res.success) {
|
|
93
|
+
return textResult(`[ERROR] 获取系统状态失败: ${res.message}`);
|
|
94
|
+
}
|
|
95
|
+
return textResult(`系统状态:\n${JSON.stringify(res.data, null, 2)}`);
|
|
96
|
+
}
|
|
97
|
+
// ── Helpers ───────────────────────────────────────────────────────────
|
|
98
|
+
function textResult(text) {
|
|
99
|
+
return { content: [{ type: "text", text }] };
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=list-kb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-kb.js","sourceRoot":"","sources":["../../tools/list-kb.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool 3 — faq_kb_manage
|
|
3
|
+
*
|
|
4
|
+
* Unified CRUD tool for FAQ items inside a knowledge base.
|
|
5
|
+
* The `action` parameter selects the operation to perform.
|
|
6
|
+
*/
|
|
7
|
+
import { type Static } from "@sinclair/typebox";
|
|
8
|
+
import type { FaqKbApiClient } from "../lib/api-client.js";
|
|
9
|
+
export declare const ManageFaqParams: import("@sinclair/typebox").TObject<{
|
|
10
|
+
action: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"create">, import("@sinclair/typebox").TLiteral<"update">, import("@sinclair/typebox").TLiteral<"delete">, import("@sinclair/typebox").TLiteral<"list">, import("@sinclair/typebox").TLiteral<"get">]>;
|
|
11
|
+
kb_id: import("@sinclair/typebox").TString;
|
|
12
|
+
faq_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
13
|
+
question: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
14
|
+
answer: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
15
|
+
node_path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
16
|
+
status: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
17
|
+
page: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
18
|
+
page_size: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
19
|
+
keyword: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
20
|
+
}>;
|
|
21
|
+
export type ManageFaqInput = Static<typeof ManageFaqParams>;
|
|
22
|
+
export declare function executeManageFaq(client: FaqKbApiClient, params: ManageFaqInput): Promise<{
|
|
23
|
+
content: {
|
|
24
|
+
type: "text";
|
|
25
|
+
text: string;
|
|
26
|
+
}[];
|
|
27
|
+
}>;
|
|
28
|
+
//# sourceMappingURL=manage-faq.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage-faq.d.ts","sourceRoot":"","sources":["../../tools/manage-faq.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,sBAAsB,CAAC;AAExE,eAAO,MAAM,eAAe;;;;;;;;;;;EA2C1B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,eAAe,CAAC,CAAC;AAE5D,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,cAAc;;;;;GAgBvB"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool 3 — faq_kb_manage
|
|
3
|
+
*
|
|
4
|
+
* Unified CRUD tool for FAQ items inside a knowledge base.
|
|
5
|
+
* The `action` parameter selects the operation to perform.
|
|
6
|
+
*/
|
|
7
|
+
import { Type } from "@sinclair/typebox";
|
|
8
|
+
export const ManageFaqParams = Type.Object({
|
|
9
|
+
action: Type.Union([
|
|
10
|
+
Type.Literal("create"),
|
|
11
|
+
Type.Literal("update"),
|
|
12
|
+
Type.Literal("delete"),
|
|
13
|
+
Type.Literal("list"),
|
|
14
|
+
Type.Literal("get"),
|
|
15
|
+
], {
|
|
16
|
+
description: "操作类型: create=创建, update=更新, delete=删除, list=列表, get=详情",
|
|
17
|
+
}),
|
|
18
|
+
kb_id: Type.String({ description: "知识库 ID" }),
|
|
19
|
+
faq_id: Type.Optional(Type.String({
|
|
20
|
+
description: "FAQ ID(update / delete / get 时必填)",
|
|
21
|
+
})),
|
|
22
|
+
question: Type.Optional(Type.String({ description: "问题内容(create / update 时填写)" })),
|
|
23
|
+
answer: Type.Optional(Type.String({ description: "答案内容(create / update 时填写)" })),
|
|
24
|
+
node_path: Type.Optional(Type.String({ description: "归属节点路径(可选)" })),
|
|
25
|
+
status: Type.Optional(Type.String({
|
|
26
|
+
description: "FAQ 状态: active / inactive(可选,默认 active)",
|
|
27
|
+
})),
|
|
28
|
+
page: Type.Optional(Type.Number({ description: "页码(list 时使用,默认 1)" })),
|
|
29
|
+
page_size: Type.Optional(Type.Number({ description: "每页大小(list 时使用,默认 20)" })),
|
|
30
|
+
keyword: Type.Optional(Type.String({ description: "关键词搜索(list 时使用)" })),
|
|
31
|
+
});
|
|
32
|
+
export async function executeManageFaq(client, params) {
|
|
33
|
+
switch (params.action) {
|
|
34
|
+
case "create":
|
|
35
|
+
return doCreate(client, params);
|
|
36
|
+
case "update":
|
|
37
|
+
return doUpdate(client, params);
|
|
38
|
+
case "delete":
|
|
39
|
+
return doDelete(client, params);
|
|
40
|
+
case "list":
|
|
41
|
+
return doList(client, params);
|
|
42
|
+
case "get":
|
|
43
|
+
return doGet(client, params);
|
|
44
|
+
default:
|
|
45
|
+
return textResult(`[ERROR] 不支持的 action: ${params.action}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
// ── Create ────────────────────────────────────────────────────────────
|
|
49
|
+
async function doCreate(client, p) {
|
|
50
|
+
if (!p.question || !p.answer) {
|
|
51
|
+
return textResult("[ERROR] 创建 FAQ 需要提供 question 和 answer");
|
|
52
|
+
}
|
|
53
|
+
const res = await client.post("/faqs", {
|
|
54
|
+
knowledge_base_id: p.kb_id,
|
|
55
|
+
question: p.question,
|
|
56
|
+
answer: p.answer,
|
|
57
|
+
node_path: p.node_path ?? "",
|
|
58
|
+
status: p.status ?? "active",
|
|
59
|
+
});
|
|
60
|
+
if (!res.success) {
|
|
61
|
+
return textResult(`[ERROR] 创建 FAQ 失败: ${res.message}`);
|
|
62
|
+
}
|
|
63
|
+
const faqId = res.data?.faq_id ?? res.data?.id ?? "unknown";
|
|
64
|
+
return textResult(`FAQ 创建成功!\n faq_id: ${faqId}\n 问题: ${p.question}\n 答案: ${p.answer?.slice(0, 80)}...`);
|
|
65
|
+
}
|
|
66
|
+
// ── Update ────────────────────────────────────────────────────────────
|
|
67
|
+
async function doUpdate(client, p) {
|
|
68
|
+
if (!p.faq_id) {
|
|
69
|
+
return textResult("[ERROR] 更新 FAQ 需要提供 faq_id");
|
|
70
|
+
}
|
|
71
|
+
if (!p.question && !p.answer) {
|
|
72
|
+
return textResult("[ERROR] 更新 FAQ 至少需要提供 question 或 answer");
|
|
73
|
+
}
|
|
74
|
+
const body = {
|
|
75
|
+
knowledge_base_id: p.kb_id,
|
|
76
|
+
};
|
|
77
|
+
if (p.question)
|
|
78
|
+
body.question = p.question;
|
|
79
|
+
if (p.answer)
|
|
80
|
+
body.answer = p.answer;
|
|
81
|
+
if (p.node_path !== undefined)
|
|
82
|
+
body.node_path = p.node_path;
|
|
83
|
+
if (p.status)
|
|
84
|
+
body.status = p.status;
|
|
85
|
+
const res = await client.put(`/faqs/${p.faq_id}`, body);
|
|
86
|
+
if (!res.success) {
|
|
87
|
+
return textResult(`[ERROR] 更新 FAQ 失败: ${res.message}`);
|
|
88
|
+
}
|
|
89
|
+
return textResult(`FAQ 更新成功! faq_id=${p.faq_id}`);
|
|
90
|
+
}
|
|
91
|
+
// ── Delete ────────────────────────────────────────────────────────────
|
|
92
|
+
async function doDelete(client, p) {
|
|
93
|
+
if (!p.faq_id) {
|
|
94
|
+
return textResult("[ERROR] 删除 FAQ 需要提供 faq_id");
|
|
95
|
+
}
|
|
96
|
+
const res = await client.del(`/faqs/${p.faq_id}?kb_id=${p.kb_id}`);
|
|
97
|
+
if (!res.success) {
|
|
98
|
+
return textResult(`[ERROR] 删除 FAQ 失败: ${res.message}`);
|
|
99
|
+
}
|
|
100
|
+
return textResult(`FAQ 删除成功! faq_id=${p.faq_id}`);
|
|
101
|
+
}
|
|
102
|
+
async function doList(client, p) {
|
|
103
|
+
const qp = new URLSearchParams({
|
|
104
|
+
knowledge_base_id: p.kb_id,
|
|
105
|
+
page: String(p.page ?? 1),
|
|
106
|
+
page_size: String(p.page_size ?? 20),
|
|
107
|
+
});
|
|
108
|
+
if (p.keyword)
|
|
109
|
+
qp.set("keyword", p.keyword);
|
|
110
|
+
if (p.status)
|
|
111
|
+
qp.set("status", p.status);
|
|
112
|
+
const res = await client.get(`/faqs?${qp.toString()}`);
|
|
113
|
+
if (!res.success) {
|
|
114
|
+
return textResult(`[ERROR] 获取 FAQ 列表失败: ${res.message}`);
|
|
115
|
+
}
|
|
116
|
+
const { faqs, pagination } = res.data;
|
|
117
|
+
const lines = [
|
|
118
|
+
`FAQ 列表(共 ${pagination.total} 条,第 ${pagination.page}/${pagination.total_pages} 页):`,
|
|
119
|
+
];
|
|
120
|
+
for (const f of faqs) {
|
|
121
|
+
const q = f.question.length > 60 ? f.question.slice(0, 57) + "..." : f.question;
|
|
122
|
+
lines.push(` [${f.id}] ${q}`);
|
|
123
|
+
}
|
|
124
|
+
return textResult(lines.join("\n"));
|
|
125
|
+
}
|
|
126
|
+
// ── Get ───────────────────────────────────────────────────────────────
|
|
127
|
+
async function doGet(client, p) {
|
|
128
|
+
if (!p.faq_id) {
|
|
129
|
+
return textResult("[ERROR] 获取 FAQ 详情需要提供 faq_id");
|
|
130
|
+
}
|
|
131
|
+
const res = await client.get(`/faqs/${p.faq_id}?kb_id=${p.kb_id}`);
|
|
132
|
+
if (!res.success) {
|
|
133
|
+
return textResult(`[ERROR] 获取 FAQ 详情失败: ${res.message}`);
|
|
134
|
+
}
|
|
135
|
+
const d = res.data;
|
|
136
|
+
return textResult([
|
|
137
|
+
`FAQ 详情:`,
|
|
138
|
+
` ID : ${d.id ?? p.faq_id}`,
|
|
139
|
+
` 问题 : ${d.question ?? ""}`,
|
|
140
|
+
` 答案 : ${d.answer ?? ""}`,
|
|
141
|
+
` 状态 : ${d.status ?? "unknown"}`,
|
|
142
|
+
` 节点路径: ${d.node_path ?? "(无)"}`,
|
|
143
|
+
].join("\n"));
|
|
144
|
+
}
|
|
145
|
+
// ── Helpers ───────────────────────────────────────────────────────────
|
|
146
|
+
function textResult(text) {
|
|
147
|
+
return { content: [{ type: "text", text }] };
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=manage-faq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage-faq.js","sourceRoot":"","sources":["../../tools/manage-faq.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool 2 — faq_kb_query
|
|
3
|
+
*
|
|
4
|
+
* Ask a question against a trained knowledge base and get an
|
|
5
|
+
* AI-generated answer with source references.
|
|
6
|
+
*/
|
|
7
|
+
import { type Static } from "@sinclair/typebox";
|
|
8
|
+
import type { FaqKbApiClient } from "../lib/api-client.js";
|
|
9
|
+
export declare const QueryParams: import("@sinclair/typebox").TObject<{
|
|
10
|
+
kb_id: import("@sinclair/typebox").TString;
|
|
11
|
+
question: import("@sinclair/typebox").TString;
|
|
12
|
+
enable_polish: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
|
|
13
|
+
user_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
14
|
+
session_id: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
15
|
+
}>;
|
|
16
|
+
export type QueryInput = Static<typeof QueryParams>;
|
|
17
|
+
export declare function executeQuery(client: FaqKbApiClient, params: QueryInput): Promise<{
|
|
18
|
+
content: {
|
|
19
|
+
type: "text";
|
|
20
|
+
text: string;
|
|
21
|
+
}[];
|
|
22
|
+
}>;
|
|
23
|
+
//# sourceMappingURL=query-kb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-kb.d.ts","sourceRoot":"","sources":["../../tools/query-kb.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAQ,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,sBAAsB,CAAC;AAExE,eAAO,MAAM,WAAW;;;;;;EAetB,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAcpD,wBAAsB,YAAY,CAChC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,UAAU;;;;;GAsCnB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool 2 — faq_kb_query
|
|
3
|
+
*
|
|
4
|
+
* Ask a question against a trained knowledge base and get an
|
|
5
|
+
* AI-generated answer with source references.
|
|
6
|
+
*/
|
|
7
|
+
import { Type } from "@sinclair/typebox";
|
|
8
|
+
export const QueryParams = Type.Object({
|
|
9
|
+
kb_id: Type.String({ description: "知识库 ID" }),
|
|
10
|
+
question: Type.String({ description: "要查询的问题" }),
|
|
11
|
+
enable_polish: Type.Optional(Type.Boolean({
|
|
12
|
+
description: "是否启用 LLM 综合分析(多 FAQ 融合生成更自然的答案)。默认 false",
|
|
13
|
+
})),
|
|
14
|
+
user_id: Type.Optional(Type.String({ description: "用户 ID(用于权限和画像)" })),
|
|
15
|
+
session_id: Type.Optional(Type.String({ description: "会话 ID(用于上下文关联)" })),
|
|
16
|
+
});
|
|
17
|
+
export async function executeQuery(client, params) {
|
|
18
|
+
const res = await client.post(`/knowledge_bases/${params.kb_id}/query`, {
|
|
19
|
+
question: params.question,
|
|
20
|
+
enable_polish: params.enable_polish ?? false,
|
|
21
|
+
user_id: params.user_id ?? null,
|
|
22
|
+
session_id: params.session_id ?? null,
|
|
23
|
+
});
|
|
24
|
+
if (!res.success) {
|
|
25
|
+
return textResult(`[ERROR] 问答失败: ${res.message}`);
|
|
26
|
+
}
|
|
27
|
+
const d = res.data;
|
|
28
|
+
const lines = [];
|
|
29
|
+
lines.push(`**答案**: ${d.answer || "(无答案)"}`);
|
|
30
|
+
if (d.faq_data?.question) {
|
|
31
|
+
lines.push(`**匹配问题**: ${d.faq_data.question}`);
|
|
32
|
+
}
|
|
33
|
+
if (d.source_nodes?.length) {
|
|
34
|
+
const topScore = d.source_nodes[0]?.score;
|
|
35
|
+
if (topScore !== undefined) {
|
|
36
|
+
lines.push(`**置信度**: ${(topScore * 100).toFixed(1)}%`);
|
|
37
|
+
}
|
|
38
|
+
lines.push(`**参考来源数**: ${d.source_nodes.length}`);
|
|
39
|
+
}
|
|
40
|
+
if (d.log_id) {
|
|
41
|
+
lines.push(`**日志 ID**: ${d.log_id}(可用于提交反馈)`);
|
|
42
|
+
}
|
|
43
|
+
return textResult(lines.join("\n"));
|
|
44
|
+
}
|
|
45
|
+
function textResult(text) {
|
|
46
|
+
return { content: [{ type: "text", text }] };
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=query-kb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-kb.js","sourceRoot":"","sources":["../../tools/query-kb.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAe,MAAM,mBAAmB,CAAC;AAGtD,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;IACrC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;IAC7C,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;IAChD,aAAa,EAAE,IAAI,CAAC,QAAQ,CAC1B,IAAI,CAAC,OAAO,CAAC;QACX,WAAW,EACT,0CAA0C;KAC7C,CAAC,CACH;IACD,OAAO,EAAE,IAAI,CAAC,QAAQ,CACpB,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAC/C;IACD,UAAU,EAAE,IAAI,CAAC,QAAQ,CACvB,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAC/C;CACF,CAAC,CAAC;AAgBH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAsB,EACtB,MAAkB;IAElB,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAC3B,oBAAoB,MAAM,CAAC,KAAK,QAAQ,EACxC;QACE,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,aAAa,EAAE,MAAM,CAAC,aAAa,IAAI,KAAK;QAC5C,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,IAAI;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,IAAI;KACtC,CACF,CAAC;IAEF,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO,UAAU,CAAC,iBAAiB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC;IACnB,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,IAAI,OAAO,EAAE,CAAC,CAAC;IAE7C,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,CAAC,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;QAC1C,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACzD,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM,WAAW,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "faq-knowledge-base",
|
|
3
|
+
"name": "FAQ Knowledge Base",
|
|
4
|
+
"description": "FAQ 知识库管理与智能问答 — 一键上传文档、AI 自动提取 FAQ、构建知识树、智能问答",
|
|
5
|
+
"configSchema": {
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"apiBaseUrl": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"default": "http://67.212.146.21:8999",
|
|
12
|
+
"description": "FAQ 知识库 API 服务地址"
|
|
13
|
+
},
|
|
14
|
+
"apiToken": {
|
|
15
|
+
"type": "string",
|
|
16
|
+
"default": "",
|
|
17
|
+
"description": "API 访问令牌(留空则自动从 /api/token 获取)"
|
|
18
|
+
},
|
|
19
|
+
"pollIntervalMs": {
|
|
20
|
+
"type": "number",
|
|
21
|
+
"default": 8000,
|
|
22
|
+
"description": "全自动管线轮询间隔(毫秒)"
|
|
23
|
+
},
|
|
24
|
+
"pipelineTimeoutMs": {
|
|
25
|
+
"type": "number",
|
|
26
|
+
"default": 1200000,
|
|
27
|
+
"description": "全自动管线超时时间(毫秒),默认 20 分钟"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@linkmind_claw/openclaw-faq-kb",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "OpenClaw Plugin - FAQ Knowledge Base: one-click document training & intelligent Q&A",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc",
|
|
10
|
+
"dev": "tsc --watch",
|
|
11
|
+
"test": "node --loader ts-node/esm test/smoke.ts"
|
|
12
|
+
},
|
|
13
|
+
"openclaw": {
|
|
14
|
+
"extensions": ["./dist/index.js"]
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"openclaw",
|
|
18
|
+
"plugin",
|
|
19
|
+
"faq",
|
|
20
|
+
"knowledge-base",
|
|
21
|
+
"rag",
|
|
22
|
+
"qa"
|
|
23
|
+
],
|
|
24
|
+
"license": "MIT",
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@sinclair/typebox": "^0.34.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"typescript": "^5.5.0",
|
|
30
|
+
"ts-node": "^10.9.0",
|
|
31
|
+
"@types/node": "^22.0.0"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: faq-knowledge-base
|
|
3
|
+
description: FAQ 知识库 — 上传文档自动训练,智能问答,FAQ 增删改查
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# FAQ Knowledge Base Skill
|
|
7
|
+
|
|
8
|
+
You have access to a FAQ Knowledge Base system that lets you:
|
|
9
|
+
|
|
10
|
+
1. **Create & train** a knowledge base from a document (PDF/DOCX/TXT/MD)
|
|
11
|
+
2. **Ask questions** against a trained knowledge base
|
|
12
|
+
3. **Manage FAQ items** (create, update, delete, list)
|
|
13
|
+
4. **Browse knowledge bases** (list, detail, delete, system status)
|
|
14
|
+
|
|
15
|
+
## Available Tools
|
|
16
|
+
|
|
17
|
+
### `faq_kb_create_and_train`
|
|
18
|
+
|
|
19
|
+
Use this when the user wants to create a new knowledge base from a document.
|
|
20
|
+
|
|
21
|
+
**When to use:**
|
|
22
|
+
- User says "create a knowledge base from this document"
|
|
23
|
+
- User provides a file URL and wants to set up a Q&A system
|
|
24
|
+
- User wants to "train" or "build" a knowledge base
|
|
25
|
+
|
|
26
|
+
**Parameters:**
|
|
27
|
+
- `kb_name` (required): Name for the knowledge base
|
|
28
|
+
- `file_url` (required): URL to the document file (PDF/DOCX/DOC/TXT/MD)
|
|
29
|
+
- `description` (optional): Description of the knowledge base
|
|
30
|
+
- `tag_name` (optional): Tag for categorization
|
|
31
|
+
|
|
32
|
+
**Notes:**
|
|
33
|
+
- This tool runs the full pipeline and may take 2-10 minutes
|
|
34
|
+
- It returns the `kb_id` which you need for subsequent queries
|
|
35
|
+
- The pipeline stages are: upload → AI extract → build tree → confirm → index
|
|
36
|
+
|
|
37
|
+
**Example:**
|
|
38
|
+
```
|
|
39
|
+
faq_kb_create_and_train({
|
|
40
|
+
kb_name: "产品手册FAQ",
|
|
41
|
+
file_url: "https://example.com/product-manual.pdf",
|
|
42
|
+
description: "产品使用手册的FAQ知识库"
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### `faq_kb_query`
|
|
47
|
+
|
|
48
|
+
Use this when the user wants to ask a question against an existing knowledge base.
|
|
49
|
+
|
|
50
|
+
**When to use:**
|
|
51
|
+
- User asks a question and you know which knowledge base to query
|
|
52
|
+
- User says "search the knowledge base for..."
|
|
53
|
+
- User wants an answer from a specific FAQ collection
|
|
54
|
+
|
|
55
|
+
**Parameters:**
|
|
56
|
+
- `kb_id` (required): The knowledge base ID (from create or list)
|
|
57
|
+
- `question` (required): The question to ask
|
|
58
|
+
- `enable_polish` (optional): Set to `true` for LLM-polished answers that synthesize multiple FAQ matches
|
|
59
|
+
- `user_id` (optional): For access control
|
|
60
|
+
- `session_id` (optional): For conversation context tracking
|
|
61
|
+
|
|
62
|
+
**Notes:**
|
|
63
|
+
- The knowledge base must be trained (is_active=true) before querying
|
|
64
|
+
- The response includes the answer, confidence score, and source references
|
|
65
|
+
- A `log_id` is returned for submitting feedback later
|
|
66
|
+
|
|
67
|
+
### `faq_kb_manage`
|
|
68
|
+
|
|
69
|
+
Use this when the user wants to manage individual FAQ items.
|
|
70
|
+
|
|
71
|
+
**When to use:**
|
|
72
|
+
- User wants to add a new Q&A pair
|
|
73
|
+
- User wants to edit or delete an existing FAQ
|
|
74
|
+
- User wants to browse FAQs in a knowledge base
|
|
75
|
+
|
|
76
|
+
**Parameters:**
|
|
77
|
+
- `action` (required): One of `create`, `update`, `delete`, `list`, `get`
|
|
78
|
+
- `kb_id` (required): Knowledge base ID
|
|
79
|
+
- `faq_id`: Required for `update`, `delete`, `get`
|
|
80
|
+
- `question`, `answer`: Required for `create`; at least one required for `update`
|
|
81
|
+
- `keyword`, `page`, `page_size`: For `list` filtering
|
|
82
|
+
|
|
83
|
+
### `faq_kb_list`
|
|
84
|
+
|
|
85
|
+
Use this when the user wants to see available knowledge bases or system info.
|
|
86
|
+
|
|
87
|
+
**When to use:**
|
|
88
|
+
- User asks "what knowledge bases do I have?"
|
|
89
|
+
- User wants details about a specific knowledge base
|
|
90
|
+
- User wants to delete a knowledge base
|
|
91
|
+
- User asks about system status
|
|
92
|
+
|
|
93
|
+
**Parameters:**
|
|
94
|
+
- `action` (required): One of `list`, `detail`, `delete`, `system_status`
|
|
95
|
+
- `kb_id`: Required for `detail` and `delete`
|
|
96
|
+
- `keyword`, `tag_name`: Optional filters for `list`
|
|
97
|
+
|
|
98
|
+
## Typical Workflows
|
|
99
|
+
|
|
100
|
+
### Workflow 1: Build a knowledge base from scratch
|
|
101
|
+
```
|
|
102
|
+
1. faq_kb_create_and_train(kb_name="...", file_url="...") → get kb_id
|
|
103
|
+
2. faq_kb_query(kb_id="...", question="...") → get answer
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Workflow 2: Query an existing knowledge base
|
|
107
|
+
```
|
|
108
|
+
1. faq_kb_list(action="list") → find kb_id
|
|
109
|
+
2. faq_kb_query(kb_id="...", question="...") → get answer
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Workflow 3: Manually build FAQ content
|
|
113
|
+
```
|
|
114
|
+
1. faq_kb_list(action="list") → find kb_id
|
|
115
|
+
2. faq_kb_manage(action="create", kb_id="...", question="...", answer="...")
|
|
116
|
+
3. faq_kb_manage(action="list", kb_id="...") → verify
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Important Notes
|
|
120
|
+
|
|
121
|
+
- All knowledge base IDs are UUIDs (e.g., `a1b2c3d4-e5f6-...`)
|
|
122
|
+
- The `faq_kb_create_and_train` tool is long-running (minutes). Be patient.
|
|
123
|
+
- Always check if a knowledge base exists before querying it.
|
|
124
|
+
- The API server is at `67.212.146.21:8999` by default.
|