@yh-ui/ai-sdk 1.0.5 → 1.0.8
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/LICENSE +1 -1
- package/README.md +44 -261
- package/package.json +3 -3
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,309 +1,92 @@
|
|
|
1
1
|
# @yh-ui/ai-sdk
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
<img src="https://raw.githubusercontent.com/1079161148/yh-ui/main/docs/public/logo.svg" width="100" height="100" alt="YH-UI Logo">
|
|
5
|
-
</p>
|
|
3
|
+
YH-UI 的 AI 交互工具包,负责把模型请求、流式输出、会话状态、工具调用和 Provider 适配整理成 Vue 项目更容易消费的 API。它可以和 `@yh-ui/components` 的 AI 组件直接配合,也可以独立用于自研界面。
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
[AI Components](https://1079161148.github.io/yh-ui/ai-components/ai-chat) | [Releases](https://github.com/1079161148/yh-ui/releases)
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
官方 AI 集成方案 · Vercel AI SDK 深度集成 · LangChain 支持 · Vue 3 响应式 Hooks · 流式渲染
|
|
11
|
-
</p>
|
|
7
|
+
## Highlights
|
|
12
8
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
</a>
|
|
20
|
-
<a href="https://github.com/1079161148/yh-ui/blob/main/LICENSE">
|
|
21
|
-
<img src="https://img.shields.io/npm/l/@yh-ui/ai-sdk.svg?style=flat-square" alt="license">
|
|
22
|
-
</a>
|
|
23
|
-
</p>
|
|
9
|
+
- Vue 响应式会话:`useAIChat`、`useAIStream`、`useConversation`、`useConversations` 管理消息、输入、加载、停止、错误和历史。
|
|
10
|
+
- 流式请求:`XRequest`、`createXRequest`、`createStreamableValue` 支持增量内容消费,适合 AI 打字机、代码生成和长文本输出。
|
|
11
|
+
- Provider 适配:内置 OpenAI、Anthropic、Google、DeepSeek、Ollama、Azure、Moonshot、MiniMax、Zhipu、SiliconFlow、Together、Novita 等 provider preset。
|
|
12
|
+
- 工具调用:`createYHFunctionTool` 统一描述工具名称、参数和执行函数,方便把 Function Calling 结果映射回业务动作。
|
|
13
|
+
- 中间件和缓存:支持请求中间件、内存缓存、localStorage/sessionStorage 缓存,便于做审计、重试和复用。
|
|
14
|
+
- Agent 扩展:包含 chain、parallel chain、Reflexion、ReWOO、Plan-Execute 等实验型 agent 组织能力。
|
|
24
15
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
## ✨ 特性
|
|
28
|
-
|
|
29
|
-
- 🤖 **多 Provider 支持** — OpenAI、Anthropic (Claude)、Google Gemini、本地模型,统一适配器接口
|
|
30
|
-
- ⚡ **Vercel AI SDK 完整集成** — `generateText`、`streamText`、`useChat`、工具调用全覆盖
|
|
31
|
-
- 🦜 **LangChain 支持** — 原生适配 LangChain 聊天模型,支持复杂 Chain/Agent 场景
|
|
32
|
-
- 💬 **Vue 3 响应式 Hooks** — `useAIChat`、`useAIStream` 等,状态自动响应视图更新
|
|
33
|
-
- 🌊 **流式渲染深度集成** — 与 `YhAiBubble` 组件无缝配合,逐词/逐字动画效果
|
|
34
|
-
- 📝 **对话历史管理** — 开箱即用的会话历史、多轮对话、持久化存储
|
|
35
|
-
- 🔧 **工具调用(Function Calling)** — 简洁的 API 定义 AI 工具函数
|
|
36
|
-
- 🔒 **完整 TypeScript** — 所有 API 均有精确类型,含 Zod schema 验证
|
|
37
|
-
|
|
38
|
-
---
|
|
39
|
-
|
|
40
|
-
## 📦 安装
|
|
16
|
+
## Install
|
|
41
17
|
|
|
42
18
|
```bash
|
|
43
|
-
# 核心包
|
|
44
19
|
pnpm add @yh-ui/ai-sdk
|
|
45
|
-
|
|
46
|
-
# 根据使用的 AI Provider 选择安装(至少一个)
|
|
47
|
-
pnpm add @ai-sdk/openai # OpenAI(GPT-4o, GPT-3.5, o1...)
|
|
48
|
-
pnpm add @ai-sdk/anthropic # Anthropic(Claude 3.5 Sonnet...)
|
|
49
|
-
pnpm add @ai-sdk/google # Google(Gemini Pro, Gemini Flash...)
|
|
50
20
|
```
|
|
51
21
|
|
|
52
|
-
|
|
22
|
+
When building a ready-made AI UI, also install the component package:
|
|
53
23
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
24
|
+
```bash
|
|
25
|
+
pnpm add @yh-ui/components
|
|
26
|
+
```
|
|
57
27
|
|
|
58
|
-
|
|
28
|
+
## Chat Hook
|
|
59
29
|
|
|
60
30
|
```vue
|
|
61
|
-
<!-- 前端组件 -->
|
|
62
31
|
<script setup lang="ts">
|
|
63
32
|
import { YhAiBubble, YhAiSender } from '@yh-ui/components'
|
|
64
33
|
import { useAIChat } from '@yh-ui/ai-sdk/vue'
|
|
65
34
|
|
|
66
35
|
const { messages, input, isLoading, sendMessage, stop } = useAIChat({
|
|
67
36
|
api: '/api/chat',
|
|
68
|
-
|
|
69
|
-
onError: (err) => console.error('请求失败:', err)
|
|
70
|
-
})
|
|
71
|
-
</script>
|
|
72
|
-
|
|
73
|
-
<template>
|
|
74
|
-
<div class="chat-container">
|
|
75
|
-
<!-- 消息列表 -->
|
|
76
|
-
<div class="messages">
|
|
77
|
-
<YhAiBubble
|
|
78
|
-
v-for="msg in messages"
|
|
79
|
-
:key="msg.id"
|
|
80
|
-
:role="msg.role"
|
|
81
|
-
:content="msg.content"
|
|
82
|
-
streaming
|
|
83
|
-
stream-mode="word"
|
|
84
|
-
:stream-interval="15"
|
|
85
|
-
/>
|
|
86
|
-
</div>
|
|
87
|
-
|
|
88
|
-
<!-- 输入框 -->
|
|
89
|
-
<YhAiSender v-model="input" :loading="isLoading" @send="sendMessage" @cancel="stop" />
|
|
90
|
-
</div>
|
|
91
|
-
</template>
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
```ts
|
|
95
|
-
// 后端 API 路由(Nuxt server/api/chat.post.ts)
|
|
96
|
-
import { streamText } from 'ai'
|
|
97
|
-
import { openai } from '@ai-sdk/openai'
|
|
98
|
-
|
|
99
|
-
export default defineEventHandler(async (event) => {
|
|
100
|
-
const { messages } = await readBody(event)
|
|
101
|
-
|
|
102
|
-
const result = await streamText({
|
|
103
|
-
model: openai('gpt-4o'),
|
|
104
|
-
messages
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
return result.toDataStreamResponse()
|
|
108
|
-
})
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
---
|
|
112
|
-
|
|
113
|
-
## 🌊 流式渲染
|
|
114
|
-
|
|
115
|
-
```vue
|
|
116
|
-
<script setup lang="ts">
|
|
117
|
-
import { YhAiBubble } from '@yh-ui/components'
|
|
118
|
-
import { useAIStream } from '@yh-ui/ai-sdk/vue'
|
|
119
|
-
|
|
120
|
-
const { content, isStreaming, start, stop } = useAIStream({
|
|
121
|
-
api: '/api/chat/stream',
|
|
122
|
-
onChunk: (chunk) => console.log('收到片段:', chunk),
|
|
123
|
-
onFinish: () => console.log('流式结束')
|
|
37
|
+
onError: (error) => console.error(error)
|
|
124
38
|
})
|
|
125
39
|
</script>
|
|
126
40
|
|
|
127
41
|
<template>
|
|
128
42
|
<YhAiBubble
|
|
129
|
-
|
|
130
|
-
:
|
|
131
|
-
:
|
|
43
|
+
v-for="message in messages"
|
|
44
|
+
:key="message.id"
|
|
45
|
+
:role="message.role"
|
|
46
|
+
:content="message.content"
|
|
132
47
|
streaming
|
|
133
|
-
stream-mode="word"
|
|
134
|
-
:stream-interval="20"
|
|
135
48
|
/>
|
|
136
|
-
<
|
|
137
|
-
<button @click="stop" :disabled="!isStreaming">停止</button>
|
|
49
|
+
<YhAiSender v-model="input" :loading="isLoading" @send="sendMessage" @cancel="stop" />
|
|
138
50
|
</template>
|
|
139
51
|
```
|
|
140
52
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
## 💬 多轮对话历史管理
|
|
53
|
+
## Provider Adapter
|
|
144
54
|
|
|
145
55
|
```ts
|
|
146
|
-
import {
|
|
147
|
-
|
|
148
|
-
const { messages, addMessage, clearHistory, exportHistory, importHistory } = useConversation({
|
|
149
|
-
maxHistory: 50, // 最大保留消息数
|
|
150
|
-
persist: true, // 持久化到 localStorage
|
|
151
|
-
storageKey: 'my-chat' // 存储 key
|
|
152
|
-
})
|
|
56
|
+
import { createProviderAdapter, getProviderPreset } from '@yh-ui/ai-sdk/vue'
|
|
153
57
|
|
|
154
|
-
|
|
155
|
-
addMessage({ role: 'user', content: '你好' })
|
|
156
|
-
addMessage({ role: 'assistant', content: '你好!有什么可以帮你的?' })
|
|
58
|
+
const preset = getProviderPreset('deepseek')
|
|
157
59
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
importHistory(json)
|
|
60
|
+
const provider = createProviderAdapter({
|
|
61
|
+
...preset,
|
|
62
|
+
apiKey: process.env.DEEPSEEK_API_KEY,
|
|
63
|
+
defaultModel: 'deepseek-chat'
|
|
64
|
+
})
|
|
164
65
|
```
|
|
165
66
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
## 🔧 工具调用(Function Calling)
|
|
67
|
+
## Function Tool
|
|
169
68
|
|
|
170
69
|
```ts
|
|
171
|
-
import { createYHFunctionTool } from '@yh-ui/ai-sdk'
|
|
172
|
-
import { z } from 'zod'
|
|
70
|
+
import { createYHFunctionTool } from '@yh-ui/ai-sdk/vue'
|
|
173
71
|
|
|
174
|
-
// 定义 AI 工具
|
|
175
72
|
const weatherTool = createYHFunctionTool({
|
|
176
73
|
name: 'get_weather',
|
|
177
|
-
description: '
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
return await res.json()
|
|
187
|
-
}
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
// 在流式对话中使用工具
|
|
191
|
-
const result = await streamText({
|
|
192
|
-
model: openai('gpt-4o'),
|
|
193
|
-
tools: { weatherTool },
|
|
194
|
-
messages: [{ role: 'user', content: '北京今天天气怎么样?' }]
|
|
74
|
+
description: 'Get weather by city',
|
|
75
|
+
parameters: {
|
|
76
|
+
type: 'object',
|
|
77
|
+
properties: {
|
|
78
|
+
city: { type: 'string' }
|
|
79
|
+
},
|
|
80
|
+
required: ['city']
|
|
81
|
+
},
|
|
82
|
+
execute: async ({ city }) => fetch(`/api/weather?city=${city}`).then((res) => res.json())
|
|
195
83
|
})
|
|
196
84
|
```
|
|
197
85
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
## 🔌 多 Provider 适配器
|
|
201
|
-
|
|
202
|
-
```ts
|
|
203
|
-
import { createProviderAdapter } from '@yh-ui/ai-sdk'
|
|
204
|
-
|
|
205
|
-
// 统一适配器,方便切换 Provider
|
|
206
|
-
const openai = createProviderAdapter({
|
|
207
|
-
name: 'openai',
|
|
208
|
-
baseUrl: 'https://api.openai.com/v1',
|
|
209
|
-
apiKey: process.env.OPENAI_API_KEY,
|
|
210
|
-
defaultModel: 'gpt-4o'
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
const anthropic = createProviderAdapter({
|
|
214
|
-
name: 'anthropic',
|
|
215
|
-
baseUrl: 'https://api.anthropic.com/v1',
|
|
216
|
-
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
217
|
-
defaultModel: 'claude-3-5-sonnet-20241022'
|
|
218
|
-
})
|
|
219
|
-
|
|
220
|
-
const gemini = createProviderAdapter({
|
|
221
|
-
name: 'google',
|
|
222
|
-
baseUrl: 'https://generativelanguage.googleapis.com/v1beta',
|
|
223
|
-
apiKey: process.env.GOOGLE_API_KEY,
|
|
224
|
-
defaultModel: 'gemini-1.5-flash'
|
|
225
|
-
})
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
---
|
|
229
|
-
|
|
230
|
-
## 📚 API 参考
|
|
231
|
-
|
|
232
|
-
### Vue Composables(从 `@yh-ui/ai-sdk/vue` 导入)
|
|
233
|
-
|
|
234
|
-
| 函数 | 说明 |
|
|
235
|
-
| ---------------------- | ------------------------------------------ |
|
|
236
|
-
| `useAIChat(options)` | AI 对话 Hook,管理消息列表、发送、流式接收 |
|
|
237
|
-
| `useAIStream(options)` | 流式文本生成 Hook |
|
|
238
|
-
|
|
239
|
-
### 核心工具(从 `@yh-ui/ai-sdk` 导入)
|
|
240
|
-
|
|
241
|
-
| 函数 | 说明 |
|
|
242
|
-
| -------------------------------- | ----------------------------------- |
|
|
243
|
-
| `useConversation(options)` | 对话历史管理(持久化、导入导出) |
|
|
244
|
-
| `createYHFunctionTool(options)` | 创建 AI 工具函数(集成 Zod 验证) |
|
|
245
|
-
| `createProviderAdapter(options)` | 创建统一 AI Provider 适配器 |
|
|
246
|
-
| `createStreamableValue()` | 创建可流式更新的响应式值 |
|
|
247
|
-
| `createAIContext()` | 创建全局 AI 上下文(Provider 模式) |
|
|
248
|
-
|
|
249
|
-
### LangChain 集成(从 `@yh-ui/ai-sdk/langchain` 导入)
|
|
250
|
-
|
|
251
|
-
```ts
|
|
252
|
-
import { YHLangChainChatModel } from '@yh-ui/ai-sdk/langchain'
|
|
253
|
-
|
|
254
|
-
const model = new YHLangChainChatModel({
|
|
255
|
-
provider: 'openai',
|
|
256
|
-
model: 'gpt-4o',
|
|
257
|
-
streaming: true
|
|
258
|
-
})
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
## 🔗 与 AI 组件配合
|
|
264
|
-
|
|
265
|
-
### `YhAiBubble` — 流式 Markdown 渲染
|
|
266
|
-
|
|
267
|
-
```vue
|
|
268
|
-
<YhAiBubble
|
|
269
|
-
role="assistant" <!-- 'user' | 'assistant' | 'system' -->
|
|
270
|
-
:content="streamContent" <!-- 支持 Markdown、代码块、表格 -->
|
|
271
|
-
:typing="isStreaming" <!-- 显示光标动效 -->
|
|
272
|
-
streaming <!-- 启用流式模式 -->
|
|
273
|
-
stream-mode="word" <!-- 'char'(逐字)| 'word'(逐词) -->
|
|
274
|
-
:stream-interval="15" <!-- 渲染间隔(ms) -->
|
|
275
|
-
/>
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
### `YhAiThoughtChain` — 思维链展示
|
|
279
|
-
|
|
280
|
-
```vue
|
|
281
|
-
<YhAiThoughtChain
|
|
282
|
-
:items="thoughtSteps"
|
|
283
|
-
status="thinking" <!-- 'thinking' | 'success' | 'error' -->
|
|
284
|
-
:show-progress="true"
|
|
285
|
-
:line-gradient="true"
|
|
286
|
-
@node-click="handleNodeClick"
|
|
287
|
-
/>
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
---
|
|
291
|
-
|
|
292
|
-
## ⚠️ 安全注意事项
|
|
293
|
-
|
|
294
|
-
1. **API Key 不要暴露到前端** — 所有 AI 调用应通过后端 API 路由进行,不要在 `.env.VITE_` 等前端可见的环境变量中存放密钥
|
|
295
|
-
2. **内容过滤** — 建议在后端对用户输入和 AI 输出做内容安全过滤
|
|
296
|
-
3. **速率限制** — 生产环境建议在 API 路由层添加用户级别的请求限流
|
|
297
|
-
|
|
298
|
-
---
|
|
299
|
-
|
|
300
|
-
## 🔗 相关资源
|
|
86
|
+
## Notes
|
|
301
87
|
|
|
302
|
-
|
|
303
|
-
- [📦 Vercel AI SDK](https://sdk.vercel.ai/docs)
|
|
304
|
-
- [🦜 LangChain.js](https://js.langchain.com/docs)
|
|
305
|
-
- [📦 GitHub 仓库](https://github.com/1079161148/yh-ui)
|
|
88
|
+
Do not expose model API keys in browser code. Keep provider credentials in a server route and stream the result to the client.
|
|
306
89
|
|
|
307
|
-
##
|
|
90
|
+
## License
|
|
308
91
|
|
|
309
|
-
MIT
|
|
92
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yh-ui/ai-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "YH-UI AI SDK integration for Vercel AI SDK and LangChain",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"vue": "^3.5.27",
|
|
37
|
-
"@yh-ui/components": "^1.0.
|
|
37
|
+
"@yh-ui/components": "^1.0.8",
|
|
38
38
|
"@langchain/core": ">=0.3.0"
|
|
39
39
|
},
|
|
40
40
|
"peerDependenciesMeta": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@langchain/core": ">=0.3.0",
|
|
47
|
-
"@yh-ui/components": "^1.0.
|
|
47
|
+
"@yh-ui/components": "^1.0.8",
|
|
48
48
|
"typescript": "^5.7.3",
|
|
49
49
|
"unbuild": "^3.3.1",
|
|
50
50
|
"vitest": "^4.0.18",
|