opc-agent 1.1.3 → 1.2.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/dist/channels/web.js +17 -17
- package/dist/core/knowledge.d.ts +5 -0
- package/dist/core/knowledge.js +39 -2
- package/dist/providers/index.d.ts +1 -1
- package/dist/providers/index.js +12 -3
- package/package.json +50 -50
- package/src/channels/web.ts +17 -17
- package/src/core/knowledge.ts +49 -4
- package/src/providers/index.ts +12 -3
- package/templates/ecommerce-assistant/README.md +45 -0
- package/templates/ecommerce-assistant/oad.yaml +47 -0
- package/templates/tech-support/README.md +43 -0
- package/templates/tech-support/oad.yaml +45 -0
package/dist/channels/web.js
CHANGED
|
@@ -27,14 +27,14 @@ const TEMPLATES_HTML = `<!DOCTYPE html>
|
|
|
27
27
|
<title>Agent Templates</title>
|
|
28
28
|
<style>
|
|
29
29
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
30
|
-
body{background:#
|
|
30
|
+
body{background:#0f0f23;color:#e0e0e0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;padding:24px}
|
|
31
31
|
h1{font-size:28px;margin-bottom:8px;color:#fff}
|
|
32
|
-
.sub{color:#
|
|
32
|
+
.sub{color:#8a8aa0;margin-bottom:32px;font-size:14px}
|
|
33
33
|
nav{margin-bottom:24px}
|
|
34
34
|
nav a{color:#818cf8;text-decoration:none;margin-right:16px;font-size:14px}
|
|
35
35
|
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px}
|
|
36
|
-
.card{background:#
|
|
37
|
-
.card:hover{border-color:#818cf8;transform:translateY(-2px)}
|
|
36
|
+
.card{background:#1a1a3a;border:1px solid #2d2d4e;border-radius:14px;padding:24px;cursor:pointer;transition:all .2s}
|
|
37
|
+
.card:hover{border-color:#818cf8;transform:translateY(-2px);box-shadow:0 4px 20px rgba(129,140,248,.15)}
|
|
38
38
|
.card .icon{font-size:32px;margin-bottom:12px}
|
|
39
39
|
.card h3{font-size:16px;color:#fff;margin-bottom:8px}
|
|
40
40
|
.card p{font-size:13px;color:#888;line-height:1.5}
|
|
@@ -65,7 +65,7 @@ const CHAT_HTML = `<!DOCTYPE html>
|
|
|
65
65
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
66
66
|
<title>OPC Agent</title>
|
|
67
67
|
<style>
|
|
68
|
-
:root{--bg:#
|
|
68
|
+
:root{--bg:#0f0f23;--surface:#1a1a3a;--border:#2d2d4e;--text:#e0e0e0;--text-dim:#8a8aa0;--accent:#818cf8;--accent-hover:#6366f1;--user-bg:#667eea;--user-hover:#5a6fd6;--error-bg:#7f1d1d;--error-text:#fca5a5;--success:#22c55e;--radius:14px}
|
|
69
69
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
70
70
|
body{background:var(--bg);color:var(--text);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',sans-serif;height:100vh;height:100dvh;display:flex;flex-direction:column;overflow:hidden}
|
|
71
71
|
header{background:var(--surface);padding:14px 20px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:12px;flex-shrink:0;backdrop-filter:blur(12px)}
|
|
@@ -88,8 +88,8 @@ nav.header-nav a:hover{color:#fff;background:rgba(255,255,255,.06)}
|
|
|
88
88
|
.msg-wrap.user{align-items:flex-end}
|
|
89
89
|
.msg-wrap.assistant{align-items:flex-start}
|
|
90
90
|
.msg{max-width:min(720px,85%);padding:10px 14px;border-radius:var(--radius);line-height:1.7;font-size:14px;word-break:break-word;position:relative;transition:all .2s}
|
|
91
|
-
.msg.user{background:
|
|
92
|
-
.msg.assistant{background
|
|
91
|
+
.msg.user{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border-bottom-right-radius:4px;box-shadow:0 2px 8px rgba(102,126,234,.35)}
|
|
92
|
+
.msg.assistant{background:#2a2a4a;color:var(--text);border:1px solid var(--border);border-bottom-left-radius:4px;box-shadow:0 2px 8px rgba(0,0,0,.25)}
|
|
93
93
|
.msg.error{background:var(--error-bg);color:var(--error-text);border:1px solid rgba(239,68,68,.3)}
|
|
94
94
|
.msg pre{background:rgba(0,0,0,.4);padding:12px;border-radius:8px;overflow-x:auto;margin:8px 0;font-size:13px;font-family:'JetBrains Mono','Fira Code','Cascadia Code',monospace;line-height:1.5}
|
|
95
95
|
.msg code{font-family:'JetBrains Mono','Fira Code','Cascadia Code',monospace;font-size:13px;background:rgba(0,0,0,.3);padding:1px 5px;border-radius:4px}
|
|
@@ -113,7 +113,7 @@ nav.header-nav a:hover{color:#fff;background:rgba(255,255,255,.06)}
|
|
|
113
113
|
#input{flex:1;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius);padding:10px 14px;color:#fff;font-size:14px;outline:none;resize:none;max-height:150px;min-height:42px;font-family:inherit;line-height:1.5;transition:border-color .2s}
|
|
114
114
|
#input:focus{border-color:var(--accent)}
|
|
115
115
|
#input::placeholder{color:var(--text-dim)}
|
|
116
|
-
#send{background:
|
|
116
|
+
#send{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;border-radius:var(--radius);padding:0 16px;height:42px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s;display:flex;align-items:center;justify-content:center;flex-shrink:0;letter-spacing:.5px}
|
|
117
117
|
#send:hover{background:var(--user-hover);transform:scale(1.05)}
|
|
118
118
|
#send:disabled{background:#334155;cursor:not-allowed;transform:none}
|
|
119
119
|
.empty-state{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--text-dim);gap:12px;padding:40px;text-align:center}
|
|
@@ -132,15 +132,15 @@ nav.header-nav a:hover{color:#fff;background:rgba(255,255,255,.06)}
|
|
|
132
132
|
<body>
|
|
133
133
|
<header>
|
|
134
134
|
<div class="avatar" id="avatar">🤖</div>
|
|
135
|
-
<div class="info"><h1 id="title">OPC Agent</h1><div class="status"><span class="dot"></span
|
|
135
|
+
<div class="info"><h1 id="title">OPC Agent</h1><div class="status"><span class="dot"></span>在线</div></div>
|
|
136
136
|
<nav class="header-nav"><a href="/dashboard">Dashboard</a><a href="/templates">Templates</a></nav>
|
|
137
137
|
</header>
|
|
138
138
|
<div id="messages">
|
|
139
|
-
<div class="empty-state" id="empty"><div class="logo">💬</div><h2
|
|
139
|
+
<div class="empty-state" id="empty"><div class="logo">💬</div><h2>开始对话</h2><p>在下方输入消息与 AI 助手对话。</p></div>
|
|
140
140
|
</div>
|
|
141
141
|
<div id="input-area">
|
|
142
|
-
<textarea id="input" rows="1" placeholder="
|
|
143
|
-
<button id="send" aria-label="
|
|
142
|
+
<textarea id="input" rows="1" placeholder="输入消息…" autocomplete="off"></textarea>
|
|
143
|
+
<button id="send" aria-label="发送">发送</button>
|
|
144
144
|
</div>
|
|
145
145
|
<script>
|
|
146
146
|
const msgs=document.getElementById('messages'),input=document.getElementById('input'),btn=document.getElementById('send'),empty=document.getElementById('empty');
|
|
@@ -193,7 +193,7 @@ async function send(){
|
|
|
193
193
|
addMsg('user',text);
|
|
194
194
|
const wrap=document.createElement('div');wrap.className='msg-wrap assistant';
|
|
195
195
|
const d=document.createElement('div');d.className='msg assistant';
|
|
196
|
-
d.innerHTML='<div class="typing"><span></span><span></span><span></span></div>';
|
|
196
|
+
d.innerHTML='<div class="typing"><span></span><span></span><span></span><small style="margin-left:6px;font-size:12px;color:#8a8aa0">思考中…</small></div>';
|
|
197
197
|
wrap.appendChild(d);
|
|
198
198
|
const time=document.createElement('div');time.className='msg-time';time.textContent=fmtTime();
|
|
199
199
|
wrap.appendChild(time);
|
|
@@ -236,17 +236,17 @@ const DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
236
236
|
<title>OPC Dashboard</title>
|
|
237
237
|
<style>
|
|
238
238
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
239
|
-
body{background:#
|
|
239
|
+
body{background:#0f0f23;color:#e0e0e0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;padding:24px}
|
|
240
240
|
h1{font-size:24px;margin-bottom:24px;color:#fff}
|
|
241
241
|
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px;margin-bottom:32px}
|
|
242
|
-
.card{background:#
|
|
243
|
-
.card .label{font-size:12px;color:#
|
|
242
|
+
.card{background:#1a1a3a;border:1px solid #2d2d4e;border-radius:14px;padding:20px}
|
|
243
|
+
.card .label{font-size:12px;color:#8a8aa0;text-transform:uppercase;letter-spacing:1px}
|
|
244
244
|
.card .value{font-size:32px;font-weight:700;color:#818cf8;margin-top:4px}
|
|
245
245
|
.card .sub{font-size:12px;color:#555;margin-top:4px}
|
|
246
246
|
nav{margin-bottom:24px}
|
|
247
247
|
nav a{color:#818cf8;text-decoration:none;margin-right:16px;font-size:14px}
|
|
248
248
|
nav a:hover{text-decoration:underline}
|
|
249
|
-
.chart{background:#
|
|
249
|
+
.chart{background:#1a1a3a;border:1px solid #2d2d4e;border-radius:14px;padding:20px;margin-bottom:16px}
|
|
250
250
|
.chart h3{font-size:14px;color:#888;margin-bottom:12px}
|
|
251
251
|
</style>
|
|
252
252
|
</head>
|
package/dist/core/knowledge.d.ts
CHANGED
|
@@ -17,6 +17,11 @@ export declare class KnowledgeBase {
|
|
|
17
17
|
}>>;
|
|
18
18
|
/** Build context string for injection into LLM calls */
|
|
19
19
|
getContext(query: string, topK?: number, minScore?: number): Promise<string>;
|
|
20
|
+
/**
|
|
21
|
+
* Query DeepBrain for semantic search enhancement.
|
|
22
|
+
* Activated when OPC_DEEPBRAIN_ENABLED=true and deepbrain CLI is globally installed.
|
|
23
|
+
*/
|
|
24
|
+
private queryDeepBrain;
|
|
20
25
|
getStats(): {
|
|
21
26
|
totalEntries: number;
|
|
22
27
|
sources: string[];
|
package/dist/core/knowledge.js
CHANGED
|
@@ -36,10 +36,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.KnowledgeBase = void 0;
|
|
37
37
|
/**
|
|
38
38
|
* Knowledge Base / RAG - Local vector storage with semantic search
|
|
39
|
+
* Supports optional DeepBrain semantic search enhancement via OPC_DEEPBRAIN_ENABLED=true
|
|
39
40
|
*/
|
|
40
41
|
const fs = __importStar(require("fs"));
|
|
41
42
|
const path = __importStar(require("path"));
|
|
42
43
|
const crypto = __importStar(require("crypto"));
|
|
44
|
+
const child_process_1 = require("child_process");
|
|
43
45
|
const CHUNK_SIZE = 500; // chars per chunk
|
|
44
46
|
const CHUNK_OVERLAP = 50;
|
|
45
47
|
const STORE_FILE = '.opc-knowledge.json';
|
|
@@ -185,9 +187,44 @@ class KnowledgeBase {
|
|
|
185
187
|
async getContext(query, topK = 3, minScore = 0.1) {
|
|
186
188
|
const results = await this.search(query, topK);
|
|
187
189
|
const relevant = results.filter(r => r.score >= minScore);
|
|
188
|
-
|
|
190
|
+
let context = '';
|
|
191
|
+
if (relevant.length > 0) {
|
|
192
|
+
context = `\n\n--- Relevant Knowledge ---\n${relevant.map((r, i) => `[${i + 1}] (source: ${r.source}, relevance: ${(r.score * 100).toFixed(0)}%)\n${r.content}`).join('\n\n')}\n--- End Knowledge ---\n`;
|
|
193
|
+
}
|
|
194
|
+
// Enhance with DeepBrain semantic search if enabled
|
|
195
|
+
const deepBrainCtx = this.queryDeepBrain(query, topK);
|
|
196
|
+
return context + deepBrainCtx;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Query DeepBrain for semantic search enhancement.
|
|
200
|
+
* Activated when OPC_DEEPBRAIN_ENABLED=true and deepbrain CLI is globally installed.
|
|
201
|
+
*/
|
|
202
|
+
queryDeepBrain(query, topK) {
|
|
203
|
+
if (process.env.OPC_DEEPBRAIN_ENABLED !== 'true')
|
|
189
204
|
return '';
|
|
190
|
-
|
|
205
|
+
// Verify deepbrain is installed
|
|
206
|
+
const check = (0, child_process_1.spawnSync)('deepbrain', ['--version'], { encoding: 'utf-8', timeout: 3000 });
|
|
207
|
+
if (check.error || check.status !== 0)
|
|
208
|
+
return '';
|
|
209
|
+
try {
|
|
210
|
+
const result = (0, child_process_1.spawnSync)('deepbrain', ['query', query, '--top', String(topK), '--format', 'json'], { encoding: 'utf-8', timeout: 5000 });
|
|
211
|
+
if (result.status !== 0 || !result.stdout?.trim())
|
|
212
|
+
return '';
|
|
213
|
+
const parsed = JSON.parse(result.stdout);
|
|
214
|
+
const items = Array.isArray(parsed)
|
|
215
|
+
? parsed
|
|
216
|
+
: (parsed.results ?? []);
|
|
217
|
+
if (items.length === 0)
|
|
218
|
+
return '';
|
|
219
|
+
return `\n\n--- DeepBrain Knowledge ---\n${items.map((r, i) => {
|
|
220
|
+
const relevance = r.score != null ? `${(r.score * 100).toFixed(0)}%` : 'n/a';
|
|
221
|
+
const text = r.content ?? r.text ?? '';
|
|
222
|
+
return `[${i + 1}] (source: ${r.source ?? 'deepbrain'}, relevance: ${relevance})\n${text}`;
|
|
223
|
+
}).join('\n\n')}\n--- End DeepBrain Knowledge ---\n`;
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
return '';
|
|
227
|
+
}
|
|
191
228
|
}
|
|
192
229
|
getStats() {
|
|
193
230
|
const sources = [...new Set(this.store.entries.map(e => String(e.metadata.source)))];
|
|
@@ -5,5 +5,5 @@ export interface LLMProvider {
|
|
|
5
5
|
chatStream(messages: Message[], systemPrompt?: string): AsyncIterable<string>;
|
|
6
6
|
}
|
|
7
7
|
export declare function createProvider(name?: string, model?: string, baseUrl?: string, apiKey?: string): LLMProvider;
|
|
8
|
-
export declare const SUPPORTED_PROVIDERS: readonly ["openai", "deepseek", "qwen", "gemini"];
|
|
8
|
+
export declare const SUPPORTED_PROVIDERS: readonly ["openai", "deepseek", "qwen", "gemini", "dashscope", "zhipu", "moonshot"];
|
|
9
9
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/providers/index.js
CHANGED
|
@@ -316,11 +316,20 @@ function isGeminiNative() {
|
|
|
316
316
|
function createProvider(name = 'openai', model, baseUrl, apiKey) {
|
|
317
317
|
const finalModel = model || process.env.OPC_LLM_MODEL || 'gpt-4o-mini';
|
|
318
318
|
const finalKey = apiKey || getApiKey();
|
|
319
|
-
|
|
319
|
+
const finalBaseUrl = baseUrl || getBaseUrl();
|
|
320
|
+
// Auto-detect Gemini native when key is new format or base URL points to googleapis
|
|
320
321
|
if (finalKey.startsWith('AQ.') || isGeminiNative()) {
|
|
321
322
|
return new GeminiNativeProvider(finalModel, finalKey);
|
|
322
323
|
}
|
|
323
|
-
|
|
324
|
+
// Auto-detect provider name from base URL
|
|
325
|
+
let resolvedName = name;
|
|
326
|
+
if (finalBaseUrl.includes('deepseek.com')) {
|
|
327
|
+
resolvedName = 'deepseek';
|
|
328
|
+
}
|
|
329
|
+
else if (finalBaseUrl.includes('dashscope.aliyuncs.com')) {
|
|
330
|
+
resolvedName = 'qwen';
|
|
331
|
+
}
|
|
332
|
+
return new OpenAICompatibleProvider(resolvedName, finalModel, baseUrl, apiKey);
|
|
324
333
|
}
|
|
325
|
-
exports.SUPPORTED_PROVIDERS = ['openai', 'deepseek', 'qwen', 'gemini'];
|
|
334
|
+
exports.SUPPORTED_PROVIDERS = ['openai', 'deepseek', 'qwen', 'gemini', 'dashscope', 'zhipu', 'moonshot'];
|
|
326
335
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "opc-agent",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Open Agent Framework — Build, test, and run AI Agents for business workstations",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"bin": {
|
|
8
|
-
"opc": "dist/cli.js"
|
|
9
|
-
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "tsc",
|
|
12
|
-
"test": "vitest run",
|
|
13
|
-
"dev": "tsc --watch",
|
|
14
|
-
"lint": "tsc --noEmit",
|
|
15
|
-
"docs:dev": "vitepress dev docs",
|
|
16
|
-
"docs:build": "vitepress build docs",
|
|
17
|
-
"docs:preview": "vitepress preview docs"
|
|
18
|
-
},
|
|
19
|
-
"keywords": [
|
|
20
|
-
"agent",
|
|
21
|
-
"ai",
|
|
22
|
-
"llm",
|
|
23
|
-
"framework",
|
|
24
|
-
"typescript",
|
|
25
|
-
"agent-framework"
|
|
26
|
-
],
|
|
27
|
-
"author": "Deepleaper",
|
|
28
|
-
"license": "Apache-2.0",
|
|
29
|
-
"repository": {
|
|
30
|
-
"type": "git",
|
|
31
|
-
"url": "https://github.com/Deepleaper/opc-agent.git"
|
|
32
|
-
},
|
|
33
|
-
"dependencies": {
|
|
34
|
-
"agentkits": "^0.1.0",
|
|
35
|
-
"commander": "^12.0.0",
|
|
36
|
-
"express": "^4.21.0",
|
|
37
|
-
"js-yaml": "^4.1.0",
|
|
38
|
-
"ws": "^8.20.0",
|
|
39
|
-
"zod": "^3.23.0"
|
|
40
|
-
},
|
|
41
|
-
"devDependencies": {
|
|
42
|
-
"@types/express": "^4.17.21",
|
|
43
|
-
"@types/js-yaml": "^4.0.9",
|
|
44
|
-
"@types/node": "^20.11.0",
|
|
45
|
-
"@types/ws": "^8.18.1",
|
|
46
|
-
"typescript": "^5.5.0",
|
|
47
|
-
"vitest": "^2.0.0",
|
|
48
|
-
"vitepress": "^1.5.0"
|
|
49
|
-
}
|
|
50
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "opc-agent",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Open Agent Framework — Build, test, and run AI Agents for business workstations",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"opc": "dist/cli.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"test": "vitest run",
|
|
13
|
+
"dev": "tsc --watch",
|
|
14
|
+
"lint": "tsc --noEmit",
|
|
15
|
+
"docs:dev": "vitepress dev docs",
|
|
16
|
+
"docs:build": "vitepress build docs",
|
|
17
|
+
"docs:preview": "vitepress preview docs"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"agent",
|
|
21
|
+
"ai",
|
|
22
|
+
"llm",
|
|
23
|
+
"framework",
|
|
24
|
+
"typescript",
|
|
25
|
+
"agent-framework"
|
|
26
|
+
],
|
|
27
|
+
"author": "Deepleaper",
|
|
28
|
+
"license": "Apache-2.0",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/Deepleaper/opc-agent.git"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"agentkits": "^0.1.0",
|
|
35
|
+
"commander": "^12.0.0",
|
|
36
|
+
"express": "^4.21.0",
|
|
37
|
+
"js-yaml": "^4.1.0",
|
|
38
|
+
"ws": "^8.20.0",
|
|
39
|
+
"zod": "^3.23.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/express": "^4.17.21",
|
|
43
|
+
"@types/js-yaml": "^4.0.9",
|
|
44
|
+
"@types/node": "^20.11.0",
|
|
45
|
+
"@types/ws": "^8.18.1",
|
|
46
|
+
"typescript": "^5.5.0",
|
|
47
|
+
"vitest": "^2.0.0",
|
|
48
|
+
"vitepress": "^1.5.0"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/channels/web.ts
CHANGED
|
@@ -26,14 +26,14 @@ const TEMPLATES_HTML = `<!DOCTYPE html>
|
|
|
26
26
|
<title>Agent Templates</title>
|
|
27
27
|
<style>
|
|
28
28
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
29
|
-
body{background:#
|
|
29
|
+
body{background:#0f0f23;color:#e0e0e0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;padding:24px}
|
|
30
30
|
h1{font-size:28px;margin-bottom:8px;color:#fff}
|
|
31
|
-
.sub{color:#
|
|
31
|
+
.sub{color:#8a8aa0;margin-bottom:32px;font-size:14px}
|
|
32
32
|
nav{margin-bottom:24px}
|
|
33
33
|
nav a{color:#818cf8;text-decoration:none;margin-right:16px;font-size:14px}
|
|
34
34
|
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px}
|
|
35
|
-
.card{background:#
|
|
36
|
-
.card:hover{border-color:#818cf8;transform:translateY(-2px)}
|
|
35
|
+
.card{background:#1a1a3a;border:1px solid #2d2d4e;border-radius:14px;padding:24px;cursor:pointer;transition:all .2s}
|
|
36
|
+
.card:hover{border-color:#818cf8;transform:translateY(-2px);box-shadow:0 4px 20px rgba(129,140,248,.15)}
|
|
37
37
|
.card .icon{font-size:32px;margin-bottom:12px}
|
|
38
38
|
.card h3{font-size:16px;color:#fff;margin-bottom:8px}
|
|
39
39
|
.card p{font-size:13px;color:#888;line-height:1.5}
|
|
@@ -65,7 +65,7 @@ const CHAT_HTML = `<!DOCTYPE html>
|
|
|
65
65
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
66
66
|
<title>OPC Agent</title>
|
|
67
67
|
<style>
|
|
68
|
-
:root{--bg:#
|
|
68
|
+
:root{--bg:#0f0f23;--surface:#1a1a3a;--border:#2d2d4e;--text:#e0e0e0;--text-dim:#8a8aa0;--accent:#818cf8;--accent-hover:#6366f1;--user-bg:#667eea;--user-hover:#5a6fd6;--error-bg:#7f1d1d;--error-text:#fca5a5;--success:#22c55e;--radius:14px}
|
|
69
69
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
70
70
|
body{background:var(--bg);color:var(--text);font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',sans-serif;height:100vh;height:100dvh;display:flex;flex-direction:column;overflow:hidden}
|
|
71
71
|
header{background:var(--surface);padding:14px 20px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:12px;flex-shrink:0;backdrop-filter:blur(12px)}
|
|
@@ -88,8 +88,8 @@ nav.header-nav a:hover{color:#fff;background:rgba(255,255,255,.06)}
|
|
|
88
88
|
.msg-wrap.user{align-items:flex-end}
|
|
89
89
|
.msg-wrap.assistant{align-items:flex-start}
|
|
90
90
|
.msg{max-width:min(720px,85%);padding:10px 14px;border-radius:var(--radius);line-height:1.7;font-size:14px;word-break:break-word;position:relative;transition:all .2s}
|
|
91
|
-
.msg.user{background:
|
|
92
|
-
.msg.assistant{background
|
|
91
|
+
.msg.user{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border-bottom-right-radius:4px;box-shadow:0 2px 8px rgba(102,126,234,.35)}
|
|
92
|
+
.msg.assistant{background:#2a2a4a;color:var(--text);border:1px solid var(--border);border-bottom-left-radius:4px;box-shadow:0 2px 8px rgba(0,0,0,.25)}
|
|
93
93
|
.msg.error{background:var(--error-bg);color:var(--error-text);border:1px solid rgba(239,68,68,.3)}
|
|
94
94
|
.msg pre{background:rgba(0,0,0,.4);padding:12px;border-radius:8px;overflow-x:auto;margin:8px 0;font-size:13px;font-family:'JetBrains Mono','Fira Code','Cascadia Code',monospace;line-height:1.5}
|
|
95
95
|
.msg code{font-family:'JetBrains Mono','Fira Code','Cascadia Code',monospace;font-size:13px;background:rgba(0,0,0,.3);padding:1px 5px;border-radius:4px}
|
|
@@ -113,7 +113,7 @@ nav.header-nav a:hover{color:#fff;background:rgba(255,255,255,.06)}
|
|
|
113
113
|
#input{flex:1;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius);padding:10px 14px;color:#fff;font-size:14px;outline:none;resize:none;max-height:150px;min-height:42px;font-family:inherit;line-height:1.5;transition:border-color .2s}
|
|
114
114
|
#input:focus{border-color:var(--accent)}
|
|
115
115
|
#input::placeholder{color:var(--text-dim)}
|
|
116
|
-
#send{background:
|
|
116
|
+
#send{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;border-radius:var(--radius);padding:0 16px;height:42px;font-size:14px;font-weight:600;cursor:pointer;transition:all .2s;display:flex;align-items:center;justify-content:center;flex-shrink:0;letter-spacing:.5px}
|
|
117
117
|
#send:hover{background:var(--user-hover);transform:scale(1.05)}
|
|
118
118
|
#send:disabled{background:#334155;cursor:not-allowed;transform:none}
|
|
119
119
|
.empty-state{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--text-dim);gap:12px;padding:40px;text-align:center}
|
|
@@ -132,15 +132,15 @@ nav.header-nav a:hover{color:#fff;background:rgba(255,255,255,.06)}
|
|
|
132
132
|
<body>
|
|
133
133
|
<header>
|
|
134
134
|
<div class="avatar" id="avatar">🤖</div>
|
|
135
|
-
<div class="info"><h1 id="title">OPC Agent</h1><div class="status"><span class="dot"></span
|
|
135
|
+
<div class="info"><h1 id="title">OPC Agent</h1><div class="status"><span class="dot"></span>在线</div></div>
|
|
136
136
|
<nav class="header-nav"><a href="/dashboard">Dashboard</a><a href="/templates">Templates</a></nav>
|
|
137
137
|
</header>
|
|
138
138
|
<div id="messages">
|
|
139
|
-
<div class="empty-state" id="empty"><div class="logo">💬</div><h2
|
|
139
|
+
<div class="empty-state" id="empty"><div class="logo">💬</div><h2>开始对话</h2><p>在下方输入消息与 AI 助手对话。</p></div>
|
|
140
140
|
</div>
|
|
141
141
|
<div id="input-area">
|
|
142
|
-
<textarea id="input" rows="1" placeholder="
|
|
143
|
-
<button id="send" aria-label="
|
|
142
|
+
<textarea id="input" rows="1" placeholder="输入消息…" autocomplete="off"></textarea>
|
|
143
|
+
<button id="send" aria-label="发送">发送</button>
|
|
144
144
|
</div>
|
|
145
145
|
<script>
|
|
146
146
|
const msgs=document.getElementById('messages'),input=document.getElementById('input'),btn=document.getElementById('send'),empty=document.getElementById('empty');
|
|
@@ -193,7 +193,7 @@ async function send(){
|
|
|
193
193
|
addMsg('user',text);
|
|
194
194
|
const wrap=document.createElement('div');wrap.className='msg-wrap assistant';
|
|
195
195
|
const d=document.createElement('div');d.className='msg assistant';
|
|
196
|
-
d.innerHTML='<div class="typing"><span></span><span></span><span></span></div>';
|
|
196
|
+
d.innerHTML='<div class="typing"><span></span><span></span><span></span><small style="margin-left:6px;font-size:12px;color:#8a8aa0">思考中…</small></div>';
|
|
197
197
|
wrap.appendChild(d);
|
|
198
198
|
const time=document.createElement('div');time.className='msg-time';time.textContent=fmtTime();
|
|
199
199
|
wrap.appendChild(time);
|
|
@@ -237,17 +237,17 @@ const DASHBOARD_HTML = `<!DOCTYPE html>
|
|
|
237
237
|
<title>OPC Dashboard</title>
|
|
238
238
|
<style>
|
|
239
239
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
240
|
-
body{background:#
|
|
240
|
+
body{background:#0f0f23;color:#e0e0e0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;padding:24px}
|
|
241
241
|
h1{font-size:24px;margin-bottom:24px;color:#fff}
|
|
242
242
|
.grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px;margin-bottom:32px}
|
|
243
|
-
.card{background:#
|
|
244
|
-
.card .label{font-size:12px;color:#
|
|
243
|
+
.card{background:#1a1a3a;border:1px solid #2d2d4e;border-radius:14px;padding:20px}
|
|
244
|
+
.card .label{font-size:12px;color:#8a8aa0;text-transform:uppercase;letter-spacing:1px}
|
|
245
245
|
.card .value{font-size:32px;font-weight:700;color:#818cf8;margin-top:4px}
|
|
246
246
|
.card .sub{font-size:12px;color:#555;margin-top:4px}
|
|
247
247
|
nav{margin-bottom:24px}
|
|
248
248
|
nav a{color:#818cf8;text-decoration:none;margin-right:16px;font-size:14px}
|
|
249
249
|
nav a:hover{text-decoration:underline}
|
|
250
|
-
.chart{background:#
|
|
250
|
+
.chart{background:#1a1a3a;border:1px solid #2d2d4e;border-radius:14px;padding:20px;margin-bottom:16px}
|
|
251
251
|
.chart h3{font-size:14px;color:#888;margin-bottom:12px}
|
|
252
252
|
</style>
|
|
253
253
|
</head>
|
package/src/core/knowledge.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Knowledge Base / RAG - Local vector storage with semantic search
|
|
3
|
+
* Supports optional DeepBrain semantic search enhancement via OPC_DEEPBRAIN_ENABLED=true
|
|
3
4
|
*/
|
|
4
5
|
import * as fs from 'fs';
|
|
5
6
|
import * as path from 'path';
|
|
6
7
|
import * as crypto from 'crypto';
|
|
8
|
+
import { spawnSync } from 'child_process';
|
|
7
9
|
|
|
8
10
|
// Simple in-memory vector store (PGlite-compatible interface for future migration)
|
|
9
11
|
interface VectorEntry {
|
|
@@ -180,11 +182,54 @@ export class KnowledgeBase {
|
|
|
180
182
|
async getContext(query: string, topK: number = 3, minScore: number = 0.1): Promise<string> {
|
|
181
183
|
const results = await this.search(query, topK);
|
|
182
184
|
const relevant = results.filter(r => r.score >= minScore);
|
|
183
|
-
if (relevant.length === 0) return '';
|
|
184
185
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
186
|
+
let context = '';
|
|
187
|
+
if (relevant.length > 0) {
|
|
188
|
+
context = `\n\n--- Relevant Knowledge ---\n${relevant.map((r, i) =>
|
|
189
|
+
`[${i + 1}] (source: ${r.source}, relevance: ${(r.score * 100).toFixed(0)}%)\n${r.content}`
|
|
190
|
+
).join('\n\n')}\n--- End Knowledge ---\n`;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Enhance with DeepBrain semantic search if enabled
|
|
194
|
+
const deepBrainCtx = this.queryDeepBrain(query, topK);
|
|
195
|
+
return context + deepBrainCtx;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Query DeepBrain for semantic search enhancement.
|
|
200
|
+
* Activated when OPC_DEEPBRAIN_ENABLED=true and deepbrain CLI is globally installed.
|
|
201
|
+
*/
|
|
202
|
+
private queryDeepBrain(query: string, topK: number): string {
|
|
203
|
+
if (process.env.OPC_DEEPBRAIN_ENABLED !== 'true') return '';
|
|
204
|
+
|
|
205
|
+
// Verify deepbrain is installed
|
|
206
|
+
const check = spawnSync('deepbrain', ['--version'], { encoding: 'utf-8', timeout: 3000 });
|
|
207
|
+
if (check.error || check.status !== 0) return '';
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
const result = spawnSync(
|
|
211
|
+
'deepbrain',
|
|
212
|
+
['query', query, '--top', String(topK), '--format', 'json'],
|
|
213
|
+
{ encoding: 'utf-8', timeout: 5000 },
|
|
214
|
+
);
|
|
215
|
+
if (result.status !== 0 || !result.stdout?.trim()) return '';
|
|
216
|
+
|
|
217
|
+
type DeepBrainResult = { source?: string; score?: number; content?: string; text?: string };
|
|
218
|
+
const parsed: unknown = JSON.parse(result.stdout);
|
|
219
|
+
const items: DeepBrainResult[] = Array.isArray(parsed)
|
|
220
|
+
? (parsed as DeepBrainResult[])
|
|
221
|
+
: ((parsed as { results?: DeepBrainResult[] }).results ?? []);
|
|
222
|
+
|
|
223
|
+
if (items.length === 0) return '';
|
|
224
|
+
|
|
225
|
+
return `\n\n--- DeepBrain Knowledge ---\n${items.map((r, i) => {
|
|
226
|
+
const relevance = r.score != null ? `${(r.score * 100).toFixed(0)}%` : 'n/a';
|
|
227
|
+
const text = r.content ?? r.text ?? '';
|
|
228
|
+
return `[${i + 1}] (source: ${r.source ?? 'deepbrain'}, relevance: ${relevance})\n${text}`;
|
|
229
|
+
}).join('\n\n')}\n--- End DeepBrain Knowledge ---\n`;
|
|
230
|
+
} catch {
|
|
231
|
+
return '';
|
|
232
|
+
}
|
|
188
233
|
}
|
|
189
234
|
|
|
190
235
|
getStats(): { totalEntries: number; sources: string[]; updatedAt: string } {
|
package/src/providers/index.ts
CHANGED
|
@@ -310,13 +310,22 @@ function isGeminiNative(): boolean {
|
|
|
310
310
|
export function createProvider(name: string = 'openai', model?: string, baseUrl?: string, apiKey?: string): LLMProvider {
|
|
311
311
|
const finalModel = model || process.env.OPC_LLM_MODEL || 'gpt-4o-mini';
|
|
312
312
|
const finalKey = apiKey || getApiKey();
|
|
313
|
+
const finalBaseUrl = baseUrl || getBaseUrl();
|
|
313
314
|
|
|
314
|
-
// Auto-detect Gemini native when key is new format
|
|
315
|
+
// Auto-detect Gemini native when key is new format or base URL points to googleapis
|
|
315
316
|
if (finalKey.startsWith('AQ.') || isGeminiNative()) {
|
|
316
317
|
return new GeminiNativeProvider(finalModel, finalKey);
|
|
317
318
|
}
|
|
318
319
|
|
|
319
|
-
|
|
320
|
+
// Auto-detect provider name from base URL
|
|
321
|
+
let resolvedName = name;
|
|
322
|
+
if (finalBaseUrl.includes('deepseek.com')) {
|
|
323
|
+
resolvedName = 'deepseek';
|
|
324
|
+
} else if (finalBaseUrl.includes('dashscope.aliyuncs.com')) {
|
|
325
|
+
resolvedName = 'qwen';
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return new OpenAICompatibleProvider(resolvedName, finalModel, baseUrl, apiKey);
|
|
320
329
|
}
|
|
321
330
|
|
|
322
|
-
export const SUPPORTED_PROVIDERS = ['openai', 'deepseek', 'qwen', 'gemini'] as const;
|
|
331
|
+
export const SUPPORTED_PROVIDERS = ['openai', 'deepseek', 'qwen', 'gemini', 'dashscope', 'zhipu', 'moonshot'] as const;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Ecommerce Assistant — 电商助手工位
|
|
2
|
+
|
|
3
|
+
专为电商平台设计的 AI 导购与售后工位,覆盖商品推荐、订单查询、退换货处理全链路。
|
|
4
|
+
|
|
5
|
+
## 快速开始
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
opc init --template ecommerce-assistant
|
|
9
|
+
opc start
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
访问 http://localhost:3000 即可使用电商助手聊天界面。
|
|
13
|
+
|
|
14
|
+
## 功能
|
|
15
|
+
|
|
16
|
+
| 技能 | 说明 |
|
|
17
|
+
|------|------|
|
|
18
|
+
| product-search | 关键词/类目/价格区间商品搜索 |
|
|
19
|
+
| order-query | 订单状态与物流实时查询 |
|
|
20
|
+
| after-sale | 退换货受理与投诉处理 |
|
|
21
|
+
| promotion | 个性化优惠券与促销推送 |
|
|
22
|
+
| recommendation | 基于偏好的个性化商品推荐 |
|
|
23
|
+
|
|
24
|
+
## 配置
|
|
25
|
+
|
|
26
|
+
在 `oad.yaml` 中修改以下参数:
|
|
27
|
+
|
|
28
|
+
- `spec.provider.default` — 切换 LLM 提供商(deepseek / openai / qwen)
|
|
29
|
+
- `spec.model` — 指定模型版本
|
|
30
|
+
- `spec.systemPrompt` — 定制品牌话术、商品范围和售后规则
|
|
31
|
+
|
|
32
|
+
### 环境变量
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
OPC_LLM_API_KEY=your_key
|
|
36
|
+
OPC_LLM_MODEL=deepseek-chat # 可选,覆盖 oad.yaml 中的 model
|
|
37
|
+
OPC_DEEPBRAIN_ENABLED=true # 启用 DeepBrain 知识库增强(需全局安装 deepbrain)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 推荐搭配
|
|
41
|
+
|
|
42
|
+
- 将商品目录、售后政策、FAQ 上传至知识库(`/api/kb/upload`)
|
|
43
|
+
- 开启 `OPC_DEEPBRAIN_ENABLED=true` 提升商品语义匹配精度
|
|
44
|
+
- 通过 Dashboard(`/dashboard`)监控转化率、客满率和退单率
|
|
45
|
+
- 结合 CRM 系统 Webhook 实现订单状态实时同步
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
apiVersion: opc/v1
|
|
2
|
+
kind: Agent
|
|
3
|
+
metadata:
|
|
4
|
+
name: ecommerce-assistant
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
description: "电商助手工位 - 商品推荐、订单查询、售后服务一体化"
|
|
7
|
+
author: Deepleaper
|
|
8
|
+
license: Apache-2.0
|
|
9
|
+
marketplace:
|
|
10
|
+
certified: false
|
|
11
|
+
category: ecommerce
|
|
12
|
+
spec:
|
|
13
|
+
provider:
|
|
14
|
+
default: deepseek
|
|
15
|
+
allowed: [openai, deepseek, qwen, gemini]
|
|
16
|
+
model: deepseek-chat
|
|
17
|
+
systemPrompt: |
|
|
18
|
+
你是一名专业的电商购物助手。
|
|
19
|
+
你帮助用户查询商品信息、比较价格、处理订单状态和售后问题。
|
|
20
|
+
根据用户需求推荐合适的商品,推送当前促销活动,并协助用户做出购买决策。
|
|
21
|
+
处理退换货申请时,需先核实订单信息,再按平台规则指引用户操作。
|
|
22
|
+
始终保持友好、热情、专业的服务态度。
|
|
23
|
+
skills:
|
|
24
|
+
- name: product-search
|
|
25
|
+
description: "搜索商品信息,支持关键词、类目、价格区间筛选"
|
|
26
|
+
- name: order-query
|
|
27
|
+
description: "查询订单状态、物流轨迹和预计送达时间"
|
|
28
|
+
- name: after-sale
|
|
29
|
+
description: "处理退换货申请、投诉受理和赔偿协商"
|
|
30
|
+
- name: promotion
|
|
31
|
+
description: "推送个性化优惠券、限时活动和会员权益"
|
|
32
|
+
- name: recommendation
|
|
33
|
+
description: "基于用户偏好和购买历史做商品推荐"
|
|
34
|
+
channels:
|
|
35
|
+
- type: web
|
|
36
|
+
port: 3000
|
|
37
|
+
memory:
|
|
38
|
+
shortTerm: true
|
|
39
|
+
longTerm: true
|
|
40
|
+
knowledge:
|
|
41
|
+
enabled: true
|
|
42
|
+
deepbrain: auto
|
|
43
|
+
dtv:
|
|
44
|
+
trust:
|
|
45
|
+
level: sandbox
|
|
46
|
+
value:
|
|
47
|
+
metrics: [conversion_rate, customer_satisfaction, avg_order_value, refund_rate]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Tech Support Agent — 技术支持工位
|
|
2
|
+
|
|
3
|
+
专为 IT 支持团队设计的 AI 工位,覆盖软件故障、系统配置、网络问题等场景。
|
|
4
|
+
|
|
5
|
+
## 快速开始
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
opc init --template tech-support
|
|
9
|
+
opc start
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
访问 http://localhost:3000 即可使用技术支持聊天界面。
|
|
13
|
+
|
|
14
|
+
## 功能
|
|
15
|
+
|
|
16
|
+
| 技能 | 说明 |
|
|
17
|
+
|------|------|
|
|
18
|
+
| troubleshoot | 分步骤诊断和解决技术问题 |
|
|
19
|
+
| knowledge-lookup | 查询技术文档与历史解决方案 |
|
|
20
|
+
| ticket-create | 创建并跟踪技术支持工单 |
|
|
21
|
+
| escalate | 升级复杂问题至专项团队 |
|
|
22
|
+
|
|
23
|
+
## 配置
|
|
24
|
+
|
|
25
|
+
在 `oad.yaml` 中修改以下参数:
|
|
26
|
+
|
|
27
|
+
- `spec.provider.default` — 切换 LLM 提供商(deepseek / openai / qwen)
|
|
28
|
+
- `spec.model` — 指定模型版本
|
|
29
|
+
- `spec.systemPrompt` — 定制支持范围和话术风格
|
|
30
|
+
|
|
31
|
+
### 环境变量
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
OPC_LLM_API_KEY=your_key
|
|
35
|
+
OPC_LLM_MODEL=deepseek-chat # 可选,覆盖 oad.yaml 中的 model
|
|
36
|
+
OPC_DEEPBRAIN_ENABLED=true # 启用 DeepBrain 知识库增强(需全局安装 deepbrain)
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 推荐搭配
|
|
40
|
+
|
|
41
|
+
- 将内部技术文档、SOP、FAQ 上传至知识库(`/api/kb/upload`)
|
|
42
|
+
- 开启 `OPC_DEEPBRAIN_ENABLED=true` 获得更精准的语义检索
|
|
43
|
+
- 通过 Dashboard(`/dashboard`)监控首次解决率和平均响应时间
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
apiVersion: opc/v1
|
|
2
|
+
kind: Agent
|
|
3
|
+
metadata:
|
|
4
|
+
name: tech-support
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
description: "技术支持工位 - 处理用户技术问题、故障排查和解决方案推荐"
|
|
7
|
+
author: Deepleaper
|
|
8
|
+
license: Apache-2.0
|
|
9
|
+
marketplace:
|
|
10
|
+
certified: false
|
|
11
|
+
category: it-support
|
|
12
|
+
spec:
|
|
13
|
+
provider:
|
|
14
|
+
default: deepseek
|
|
15
|
+
allowed: [openai, deepseek, qwen, gemini]
|
|
16
|
+
model: deepseek-chat
|
|
17
|
+
systemPrompt: |
|
|
18
|
+
你是一名专业的技术支持工程师。
|
|
19
|
+
你帮助用户解决技术问题,包括软件故障、系统配置、网络问题、硬件故障等。
|
|
20
|
+
回答时请保持专业、耐心,并提供清晰的步骤指引。
|
|
21
|
+
优先使用知识库中的已知解决方案。
|
|
22
|
+
如果问题无法远程解决,请指导用户联系线下支持或提交工单。
|
|
23
|
+
skills:
|
|
24
|
+
- name: troubleshoot
|
|
25
|
+
description: "诊断和解决技术问题,提供分步骤操作指南"
|
|
26
|
+
- name: knowledge-lookup
|
|
27
|
+
description: "查询技术文档、FAQ 和历史解决方案库"
|
|
28
|
+
- name: ticket-create
|
|
29
|
+
description: "为复杂问题创建技术支持工单并跟踪进展"
|
|
30
|
+
- name: escalate
|
|
31
|
+
description: "将高优先级问题升级到高级工程师或专项团队"
|
|
32
|
+
channels:
|
|
33
|
+
- type: web
|
|
34
|
+
port: 3000
|
|
35
|
+
memory:
|
|
36
|
+
shortTerm: true
|
|
37
|
+
longTerm: true
|
|
38
|
+
knowledge:
|
|
39
|
+
enabled: true
|
|
40
|
+
deepbrain: auto
|
|
41
|
+
dtv:
|
|
42
|
+
trust:
|
|
43
|
+
level: internal
|
|
44
|
+
value:
|
|
45
|
+
metrics: [resolution_time, first_contact_resolution, customer_satisfaction]
|