gimc-ai-agent 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 +299 -0
- package/dist/App.vue.d.ts +3 -0
- package/dist/api/request.d.ts +33 -0
- package/dist/assets/icons.d.ts +3 -0
- package/dist/components/AiAgent.vue.d.ts +82 -0
- package/dist/gimc-ai-agent.es.js +3123 -0
- package/dist/gimc-ai-agent.umd.js +7 -0
- package/dist/index.d.ts +10 -0
- package/dist/main.d.ts +1 -0
- package/dist/style.css +1 -0
- package/dist/types/index.d.ts +76 -0
- package/dist/utils/api/ragKnowledge.d.ts +163 -0
- package/dist/utils/http/index.d.ts +7 -0
- package/dist/utils/http/status.d.ts +1 -0
- package/dist/utils/http/type.d.ts +9 -0
- package/dist/utils/tokenManager.d.ts +21 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
# gimc-ai-agent
|
|
2
|
+
|
|
3
|
+
AI 智能客服 Vue3 组件,基于 RAG 知识库的智能问答系统。
|
|
4
|
+
|
|
5
|
+
## 安装
|
|
6
|
+
|
|
7
|
+
### 1. 安装组件
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install gimc-ai-agent
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### 2. 安装前置依赖
|
|
14
|
+
|
|
15
|
+
本组件依赖 `element-plus`,请确保项目中已安装:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install element-plus @element-plus/icons-vue
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### 3. 配置 main.ts
|
|
22
|
+
|
|
23
|
+
在项目入口文件中引入 Element Plus 和组件样式:
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// main.ts
|
|
27
|
+
import { createApp } from 'vue'
|
|
28
|
+
import App from './App.vue'
|
|
29
|
+
import ElementPlus from 'element-plus'
|
|
30
|
+
import 'element-plus/dist/index.css'
|
|
31
|
+
import 'gimc-ai-agent/dist/style.css'
|
|
32
|
+
|
|
33
|
+
const app = createApp(App)
|
|
34
|
+
app.use(ElementPlus)
|
|
35
|
+
app.mount('#app')
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 4. 在组件中使用
|
|
39
|
+
|
|
40
|
+
```vue
|
|
41
|
+
<template>
|
|
42
|
+
<!-- 建议配合登录状态控制显示 -->
|
|
43
|
+
<GimcAiAgent
|
|
44
|
+
v-if="isLoggedIn"
|
|
45
|
+
ref="agentRef"
|
|
46
|
+
:rag-knowledge-id="1"
|
|
47
|
+
:token="userToken"
|
|
48
|
+
title="智能客服"
|
|
49
|
+
@send="onSend"
|
|
50
|
+
@feedback="onFeedback"
|
|
51
|
+
@satisfaction="onSatisfaction"
|
|
52
|
+
/>
|
|
53
|
+
</template>
|
|
54
|
+
|
|
55
|
+
<script setup lang="ts">
|
|
56
|
+
import { ref, computed } from 'vue'
|
|
57
|
+
import { GimcAiAgent } from 'gimc-ai-agent'
|
|
58
|
+
import type { FeedbackData } from 'gimc-ai-agent'
|
|
59
|
+
|
|
60
|
+
const agentRef = ref()
|
|
61
|
+
|
|
62
|
+
// 登录状态判断(根据实际业务修改)
|
|
63
|
+
const userToken = computed(() => localStorage.getItem('token') || '')
|
|
64
|
+
const isLoggedIn = computed(() => !!userToken.value)
|
|
65
|
+
|
|
66
|
+
// 事件监听
|
|
67
|
+
const onSend = (msg: string) => {
|
|
68
|
+
console.log('用户发送:', msg)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const onFeedback = (data: FeedbackData) => {
|
|
72
|
+
console.log('用户反馈:', data)
|
|
73
|
+
// 上报到后端
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const onSatisfaction = (score: number) => {
|
|
77
|
+
console.log('满意度评分:', score)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// 主动调用方法
|
|
81
|
+
const openAgent = () => agentRef.value?.open()
|
|
82
|
+
const closeAgent = () => agentRef.value?.close()
|
|
83
|
+
const clearMessages = () => agentRef.value?.clearMessages()
|
|
84
|
+
</script>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## 完整安装步骤总结
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# 1. 安装组件和依赖
|
|
91
|
+
npm install gimc-ai-agent element-plus @element-plus/icons-vue
|
|
92
|
+
|
|
93
|
+
# 2. 在 main.ts 中配置
|
|
94
|
+
# - 引入 ElementPlus 并 use
|
|
95
|
+
# - 引入 'element-plus/dist/index.css'
|
|
96
|
+
# - 引入 'gimc-ai-agent/dist/style.css'
|
|
97
|
+
|
|
98
|
+
# 3. 在需要的页面中引入组件使用
|
|
99
|
+
# import { GimcAiAgent } from 'gimc-ai-agent'
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Props
|
|
103
|
+
|
|
104
|
+
| 属性 | 类型 | 默认值 | 必填 | 说明 |
|
|
105
|
+
|------|------|--------|------|------|
|
|
106
|
+
| `ragKnowledgeId` | `number` | - | ✅ | RAG 知识库 ID |
|
|
107
|
+
| `token` | `string` | - | - | 外部系统传入的认证 token(优先级高于 localStorage) |
|
|
108
|
+
| `title` | `string` | `'灵犀AI小助手'` | - | 标题 |
|
|
109
|
+
| `avatar` | `string` | 内置图标 | - | 头像 URL |
|
|
110
|
+
| `floatIcon` | `string` | 内置图标 | - | 悬浮按钮图标 URL |
|
|
111
|
+
| `position` | `{ right?: number; bottom?: number }` | `{ right: 8, bottom: 24 }` | - | 位置配置(单位:px) |
|
|
112
|
+
| `width` | `number` | `560` | - | 弹窗宽度(单位:px) |
|
|
113
|
+
| `welcomeText` | `string` | `'有任何问题,随时问我~'` | - | 欢迎语 |
|
|
114
|
+
| `idleTimeout` | `number` | `180000` | - | 空闲超时时间(ms) |
|
|
115
|
+
| `typingSpeed` | `number` | `30` | - | 打字机速度(ms) |
|
|
116
|
+
| `showSatisfaction` | `boolean` | `true` | - | 是否显示满意度评价 |
|
|
117
|
+
| `showFeedback` | `boolean` | `true` | - | 是否显示反馈功能 |
|
|
118
|
+
|
|
119
|
+
## Events
|
|
120
|
+
|
|
121
|
+
| 事件 | 参数 | 说明 |
|
|
122
|
+
|------|------|------|
|
|
123
|
+
| `open` | - | 弹窗打开时触发 |
|
|
124
|
+
| `close` | - | 弹窗关闭时触发 |
|
|
125
|
+
| `send` | `message: string` | 用户发送消息时触发 |
|
|
126
|
+
| `feedback` | `FeedbackData` | 用户提交反馈时触发 |
|
|
127
|
+
| `satisfaction` | `score: number` | 用户评分时触发(1-5) |
|
|
128
|
+
| `article-click` | `Article` | 点击文章时触发 |
|
|
129
|
+
| `session-end` | - | 会话自动结束时触发 |
|
|
130
|
+
|
|
131
|
+
## Slots
|
|
132
|
+
|
|
133
|
+
| 插槽名 | 说明 |
|
|
134
|
+
|--------|------|
|
|
135
|
+
| `float-button` | 自定义悬浮按钮 |
|
|
136
|
+
| `header` | 自定义头部区域 |
|
|
137
|
+
| `welcome` | 自定义欢迎区域 |
|
|
138
|
+
| `quick-actions` | 自定义快捷操作区域 |
|
|
139
|
+
|
|
140
|
+
## Expose 方法
|
|
141
|
+
|
|
142
|
+
| 方法 | 说明 |
|
|
143
|
+
|------|------|
|
|
144
|
+
| `open()` | 打开弹窗 |
|
|
145
|
+
| `close()` | 关闭弹窗 |
|
|
146
|
+
| `clearMessages()` | 清空消息记录 |
|
|
147
|
+
| `sendMessage(content: string)` | 主动发送消息 |
|
|
148
|
+
|
|
149
|
+
## 类型定义
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
interface Message {
|
|
153
|
+
role: 'user' | 'assistant'
|
|
154
|
+
content: string
|
|
155
|
+
timestamp?: string
|
|
156
|
+
showFeedback?: boolean
|
|
157
|
+
feedback?: 'resolved' | 'unresolved' | null
|
|
158
|
+
suggestions?: string[]
|
|
159
|
+
isTyping?: boolean
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
interface Article {
|
|
163
|
+
title: string
|
|
164
|
+
url: string
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
interface QuickAction {
|
|
168
|
+
label: string
|
|
169
|
+
icon?: string
|
|
170
|
+
onClick?: () => void
|
|
171
|
+
url?: string
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
interface FeedbackData {
|
|
175
|
+
messageId: string
|
|
176
|
+
type: string
|
|
177
|
+
resolved: boolean
|
|
178
|
+
detail?: string
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
interface Position {
|
|
182
|
+
right?: number
|
|
183
|
+
bottom?: number
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## 登录状态控制
|
|
188
|
+
|
|
189
|
+
组件本身不包含登录校验逻辑,建议在业务系统中通过 `v-if` 控制显示:
|
|
190
|
+
|
|
191
|
+
```vue
|
|
192
|
+
<template>
|
|
193
|
+
<!-- 方式1:使用 Pinia store -->
|
|
194
|
+
<GimcAiAgent
|
|
195
|
+
v-if="userStore.isLoggedIn"
|
|
196
|
+
:rag-knowledge-id="1"
|
|
197
|
+
:token="userStore.token"
|
|
198
|
+
/>
|
|
199
|
+
|
|
200
|
+
<!-- 方式2:使用 computed token 判断 -->
|
|
201
|
+
<GimcAiAgent
|
|
202
|
+
v-if="!!token"
|
|
203
|
+
:rag-knowledge-id="1"
|
|
204
|
+
:token="token"
|
|
205
|
+
/>
|
|
206
|
+
</template>
|
|
207
|
+
|
|
208
|
+
<script setup>
|
|
209
|
+
import { computed } from 'vue'
|
|
210
|
+
import { useUserStore } from '@/stores/user'
|
|
211
|
+
|
|
212
|
+
const userStore = useUserStore()
|
|
213
|
+
const token = computed(() => localStorage.getItem('token'))
|
|
214
|
+
</script>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Token 认证配置
|
|
218
|
+
|
|
219
|
+
组件支持两种 token 传递方式:
|
|
220
|
+
|
|
221
|
+
### 方式1:通过 prop 传递(推荐用于外部系统集成)
|
|
222
|
+
|
|
223
|
+
当组件被外部系统调用时,可以通过 `token` prop 传递认证令牌:
|
|
224
|
+
|
|
225
|
+
```vue
|
|
226
|
+
<template>
|
|
227
|
+
<GimcAiAgent
|
|
228
|
+
:rag-knowledge-id="1"
|
|
229
|
+
:token="externalToken"
|
|
230
|
+
/>
|
|
231
|
+
</template>
|
|
232
|
+
|
|
233
|
+
<script setup>
|
|
234
|
+
import { ref } from 'vue'
|
|
235
|
+
import { GimcAiAgent } from 'gimc-ai-agent'
|
|
236
|
+
|
|
237
|
+
// 外部系统传入的 token
|
|
238
|
+
const externalToken = ref('your-external-token-here')
|
|
239
|
+
</script>
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### 方式2:使用 localStorage(默认兼容)
|
|
243
|
+
|
|
244
|
+
如果没有传递 `token` prop,组件会自动从 `localStorage` 中读取 `gimc-ai-agent-token`:
|
|
245
|
+
|
|
246
|
+
```javascript
|
|
247
|
+
// 在登录成功后设置 token
|
|
248
|
+
localStorage.setItem('gimc-ai-agent-token', 'your-token-here')
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**优先级说明**:
|
|
252
|
+
- 如果同时存在 `token` prop 和 localStorage 中的 token,优先使用 `token` prop
|
|
253
|
+
- 这样可以确保外部系统集成时的灵活性
|
|
254
|
+
|
|
255
|
+
## RAG 知识库配置
|
|
256
|
+
|
|
257
|
+
本组件需要配合 RAG 知识库后端使用。确保:
|
|
258
|
+
|
|
259
|
+
1. 后端已部署 RAG 知识库服务
|
|
260
|
+
2. 创建知识库并获取 `ragKnowledgeId`
|
|
261
|
+
3. 配置好后端 API 地址(通过环境变量)
|
|
262
|
+
4. 确保用户已通过认证(提供有效的 token)
|
|
263
|
+
|
|
264
|
+
## 自定义插槽示例
|
|
265
|
+
|
|
266
|
+
```vue
|
|
267
|
+
<GimcAiAgent :rag-knowledge-id="1" :token="token">
|
|
268
|
+
<template #float-button>
|
|
269
|
+
<div class="custom-button">
|
|
270
|
+
<img src="/custom-icon.png" />
|
|
271
|
+
</div>
|
|
272
|
+
</template>
|
|
273
|
+
|
|
274
|
+
<template #welcome>
|
|
275
|
+
<div class="custom-welcome">
|
|
276
|
+
<h2>欢迎使用智能助手</h2>
|
|
277
|
+
<p>我可以帮你解答各种问题</p>
|
|
278
|
+
</div>
|
|
279
|
+
</template>
|
|
280
|
+
</GimcAiAgent>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## 后端接口要求
|
|
284
|
+
|
|
285
|
+
组件会调用以下后端接口(基于配置的 API 地址):
|
|
286
|
+
|
|
287
|
+
- `POST /api/rag-knowledge/answer/stream` - 流式问答接口
|
|
288
|
+
- `GET /api/rag-knowledge/session/list` - 获取会话列表
|
|
289
|
+
- `GET /api/rag-knowledge/session/messages` - 获取历史消息
|
|
290
|
+
- `GET /api/rag-knowledge/questions/suggested` - 获取推荐问题
|
|
291
|
+
- `GET /api/rag-knowledge/questions/recommended` - 获取相关问题
|
|
292
|
+
- `POST /api/rag-knowledge/feedback` - 提交反馈
|
|
293
|
+
- `PUT /api/rag-knowledge/feedback` - 更新反馈
|
|
294
|
+
- `DELETE /api/rag-knowledge/feedback/{id}` - 删除反馈
|
|
295
|
+
- `POST /api/rag-knowledge/stop` - 停止生成
|
|
296
|
+
|
|
297
|
+
## License
|
|
298
|
+
|
|
299
|
+
MIT
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
+
declare const _default: typeof __VLS_export;
|
|
3
|
+
export default _default;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { AxiosRequestConfig } from 'axios';
|
|
2
|
+
interface RequestConfig extends AxiosRequestConfig {
|
|
3
|
+
singleThread?: boolean;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* 配置 API
|
|
7
|
+
*/
|
|
8
|
+
export declare function setApiConfig(config: {
|
|
9
|
+
baseUrl?: string;
|
|
10
|
+
token?: string;
|
|
11
|
+
headers?: Record<string, string>;
|
|
12
|
+
}): void;
|
|
13
|
+
/**
|
|
14
|
+
* 获取当前配置
|
|
15
|
+
*/
|
|
16
|
+
export declare function getApiConfig(): {
|
|
17
|
+
baseUrl: string;
|
|
18
|
+
token: string;
|
|
19
|
+
headers: Record<string, string>;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* 通用请求方法
|
|
23
|
+
*/
|
|
24
|
+
export declare function request<T = any>(config: RequestConfig): Promise<T>;
|
|
25
|
+
/**
|
|
26
|
+
* GET 请求
|
|
27
|
+
*/
|
|
28
|
+
export declare function get<T = any>(url: string, config?: RequestConfig): Promise<T>;
|
|
29
|
+
/**
|
|
30
|
+
* POST 请求
|
|
31
|
+
*/
|
|
32
|
+
export declare function post<T = any>(url: string, data?: any, config?: RequestConfig): Promise<T>;
|
|
33
|
+
export default request;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { Article, FeedbackData } from '../types';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
/** RAG 知识库 ID(必填) */
|
|
4
|
+
ragKnowledgeId: number;
|
|
5
|
+
/** 标题 */
|
|
6
|
+
title?: string;
|
|
7
|
+
/** 头像 URL */
|
|
8
|
+
avatar?: string;
|
|
9
|
+
/** 悬浮按钮图标 URL */
|
|
10
|
+
floatIcon?: string;
|
|
11
|
+
/** 位置配置 */
|
|
12
|
+
position?: {
|
|
13
|
+
right?: number;
|
|
14
|
+
bottom?: number;
|
|
15
|
+
};
|
|
16
|
+
/** 弹窗宽度 */
|
|
17
|
+
width?: number;
|
|
18
|
+
/** 欢迎语 */
|
|
19
|
+
welcomeText?: string;
|
|
20
|
+
/** 空闲超时时间(ms) */
|
|
21
|
+
idleTimeout?: number;
|
|
22
|
+
/** 打字机速度(ms) */
|
|
23
|
+
typingSpeed?: number;
|
|
24
|
+
/** 是否显示满意度评价 */
|
|
25
|
+
showSatisfaction?: boolean;
|
|
26
|
+
/** 是否显示反馈功能 */
|
|
27
|
+
showFeedback?: boolean;
|
|
28
|
+
/** 外部系统传入的 token */
|
|
29
|
+
token?: string;
|
|
30
|
+
};
|
|
31
|
+
declare var __VLS_1: {}, __VLS_9: {}, __VLS_24: {}, __VLS_125: {};
|
|
32
|
+
type __VLS_Slots = {} & {
|
|
33
|
+
'float-button'?: (props: typeof __VLS_1) => any;
|
|
34
|
+
} & {
|
|
35
|
+
header?: (props: typeof __VLS_9) => any;
|
|
36
|
+
} & {
|
|
37
|
+
welcome?: (props: typeof __VLS_24) => any;
|
|
38
|
+
} & {
|
|
39
|
+
'quick-actions'?: (props: typeof __VLS_125) => any;
|
|
40
|
+
};
|
|
41
|
+
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {
|
|
42
|
+
open: () => void;
|
|
43
|
+
close: () => void;
|
|
44
|
+
clearMessages: () => void;
|
|
45
|
+
sendMessage: (content: string) => Promise<void>;
|
|
46
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
47
|
+
open: () => any;
|
|
48
|
+
close: () => any;
|
|
49
|
+
send: (message: string) => any;
|
|
50
|
+
feedback: (data: FeedbackData) => any;
|
|
51
|
+
satisfaction: (score: number) => any;
|
|
52
|
+
"article-click": (article: Article) => any;
|
|
53
|
+
"session-end": () => any;
|
|
54
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
55
|
+
onOpen?: (() => any) | undefined;
|
|
56
|
+
onClose?: (() => any) | undefined;
|
|
57
|
+
onSend?: ((message: string) => any) | undefined;
|
|
58
|
+
onFeedback?: ((data: FeedbackData) => any) | undefined;
|
|
59
|
+
onSatisfaction?: ((score: number) => any) | undefined;
|
|
60
|
+
"onArticle-click"?: ((article: Article) => any) | undefined;
|
|
61
|
+
"onSession-end"?: (() => any) | undefined;
|
|
62
|
+
}>, {
|
|
63
|
+
title: string;
|
|
64
|
+
position: {
|
|
65
|
+
right?: number;
|
|
66
|
+
bottom?: number;
|
|
67
|
+
};
|
|
68
|
+
width: number;
|
|
69
|
+
welcomeText: string;
|
|
70
|
+
idleTimeout: number;
|
|
71
|
+
typingSpeed: number;
|
|
72
|
+
showSatisfaction: boolean;
|
|
73
|
+
showFeedback: boolean;
|
|
74
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
75
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
76
|
+
declare const _default: typeof __VLS_export;
|
|
77
|
+
export default _default;
|
|
78
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
79
|
+
new (): {
|
|
80
|
+
$slots: S;
|
|
81
|
+
};
|
|
82
|
+
};
|