plugin-ai-api 1.0.9 → 1.0.10
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/externalVersion.js +9 -9
- package/dist/server/routes/agent-completions.js +108 -42
- package/dist/server/routes/chat-completions.js +103 -19
- package/dist/server/routes/completions.js +37 -15
- package/dist/server/routes/router.js +20 -4
- package/dist/server/usage.js +5 -4
- package/dist/server/utils/openai-format.js +11 -2
- package/dist/server/utils/streaming.js +80 -0
- package/dist/swagger.js +38 -4
- package/package.json +3 -2
- package/src/server/__tests__/openai-format.test.ts +52 -0
- package/src/server/routes/agent-completions.ts +121 -54
- package/src/server/routes/chat-completions.ts +406 -318
- package/src/server/routes/completions.ts +322 -299
- package/src/server/routes/router.ts +19 -3
- package/src/server/usage.ts +7 -4
- package/src/server/utils/ai-employee-runtime.ts +1 -1
- package/src/server/utils/openai-format.ts +164 -142
- package/src/server/utils/streaming.ts +46 -0
- package/src/swagger.ts +359 -325
package/src/swagger.ts
CHANGED
|
@@ -1,325 +1,359 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This file is part of the NocoBase (R) project.
|
|
3
|
-
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
-
* Authors: NocoBase Team.
|
|
5
|
-
*
|
|
6
|
-
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
-
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
export default {
|
|
11
|
-
info: {
|
|
12
|
-
title: 'NocoBase API - AI API Plugin',
|
|
13
|
-
description: 'OpenAI-compatible AI gateway and configuration API',
|
|
14
|
-
},
|
|
15
|
-
tags: [
|
|
16
|
-
{ name: 'aiApiConfig', description: 'AI API configuration management' },
|
|
17
|
-
{ name: 'ai-llm', description: 'OpenAI-compatible LLM gateway (prefix: /api/ai-llm/v1)' },
|
|
18
|
-
],
|
|
19
|
-
paths: {
|
|
20
|
-
'/aiApiConfig:get': {
|
|
21
|
-
get: {
|
|
22
|
-
tags: ['aiApiConfig'],
|
|
23
|
-
summary: 'Get AI API configuration',
|
|
24
|
-
security: [{ BearerAuth: [] }],
|
|
25
|
-
responses: {
|
|
26
|
-
200: {
|
|
27
|
-
description: 'Current AI API configuration',
|
|
28
|
-
content: {
|
|
29
|
-
'application/json': {
|
|
30
|
-
schema: { $ref: '#/components/schemas/AiApiConfig' },
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
'/aiApiConfig:save': {
|
|
38
|
-
post: {
|
|
39
|
-
tags: ['aiApiConfig'],
|
|
40
|
-
summary: 'Save AI API configuration',
|
|
41
|
-
security: [{ BearerAuth: [] }],
|
|
42
|
-
requestBody: {
|
|
43
|
-
required: true,
|
|
44
|
-
content: {
|
|
45
|
-
'application/json': {
|
|
46
|
-
schema: { $ref: '#/components/schemas/AiApiConfig' },
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
responses: {
|
|
51
|
-
200: { description: 'Configuration saved successfully' },
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
'/ai-llm/v1/models': {
|
|
56
|
-
get: {
|
|
57
|
-
tags: ['ai-llm'],
|
|
58
|
-
summary: 'List available models',
|
|
59
|
-
description:
|
|
60
|
-
'Returns all LLM models available across registered services. Model IDs are formatted as `serviceName/modelId`.',
|
|
61
|
-
security: [{ BearerAuth: [] }],
|
|
62
|
-
responses: {
|
|
63
|
-
200: {
|
|
64
|
-
description: 'List of available models',
|
|
65
|
-
content: {
|
|
66
|
-
'application/json': {
|
|
67
|
-
schema: {
|
|
68
|
-
type: 'object',
|
|
69
|
-
properties: {
|
|
70
|
-
object: { type: 'string', example: 'list' },
|
|
71
|
-
data: {
|
|
72
|
-
type: 'array',
|
|
73
|
-
items: { $ref: '#/components/schemas/ModelObject' },
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
},
|
|
83
|
-
'/ai-llm/v1/models/{id}': {
|
|
84
|
-
get: {
|
|
85
|
-
tags: ['ai-llm'],
|
|
86
|
-
summary: 'Get model details',
|
|
87
|
-
security: [{ BearerAuth: [] }],
|
|
88
|
-
parameters: [
|
|
89
|
-
{
|
|
90
|
-
name: 'id',
|
|
91
|
-
in: 'path',
|
|
92
|
-
required: true,
|
|
93
|
-
description: 'Model ID in format `serviceName/modelId`',
|
|
94
|
-
schema: { type: 'string', example: 'openai/gpt-4o' },
|
|
95
|
-
},
|
|
96
|
-
],
|
|
97
|
-
responses: {
|
|
98
|
-
200: {
|
|
99
|
-
description: 'Model details',
|
|
100
|
-
content: {
|
|
101
|
-
'application/json': {
|
|
102
|
-
schema: { $ref: '#/components/schemas/ModelObject' },
|
|
103
|
-
},
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
404: { description: 'Model not found' },
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
},
|
|
110
|
-
'/ai-llm/v1/chat/completions': {
|
|
111
|
-
post: {
|
|
112
|
-
tags: ['ai-llm'],
|
|
113
|
-
summary: 'Chat completions',
|
|
114
|
-
description:
|
|
115
|
-
'OpenAI-compatible chat completions endpoint. Supports streaming (`stream: true`). Use header `X-AI-Mode: llm` (default) or `X-AI-Mode: agent` to switch between direct LLM and agent mode.',
|
|
116
|
-
security: [{ BearerAuth: [] }],
|
|
117
|
-
parameters: [
|
|
118
|
-
{
|
|
119
|
-
name: 'X-AI-Mode',
|
|
120
|
-
in: 'header',
|
|
121
|
-
required: false,
|
|
122
|
-
description: 'AI mode: `llm` (default) or `agent`',
|
|
123
|
-
schema: { type: 'string', enum: ['llm', 'agent'], default: 'llm' },
|
|
124
|
-
},
|
|
125
|
-
],
|
|
126
|
-
requestBody: {
|
|
127
|
-
required: true,
|
|
128
|
-
content: {
|
|
129
|
-
'application/json': {
|
|
130
|
-
schema: { $ref: '#/components/schemas/ChatCompletionRequest' },
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
},
|
|
134
|
-
responses: {
|
|
135
|
-
200: {
|
|
136
|
-
description: 'Chat completion response (or SSE stream when `stream: true`)',
|
|
137
|
-
content: {
|
|
138
|
-
'application/json': {
|
|
139
|
-
schema: { $ref: '#/components/schemas/ChatCompletionResponse' },
|
|
140
|
-
},
|
|
141
|
-
'text/event-stream': {
|
|
142
|
-
schema: { type: 'string', description: 'SSE stream of completion chunks' },
|
|
143
|
-
},
|
|
144
|
-
},
|
|
145
|
-
},
|
|
146
|
-
429: { description: 'Rate limit exceeded' },
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
'/ai-llm/v1/completions': {
|
|
151
|
-
post: {
|
|
152
|
-
tags: ['ai-llm'],
|
|
153
|
-
summary: 'Text completions (legacy)',
|
|
154
|
-
description: 'Legacy text completions for LiteLLM compatibility.',
|
|
155
|
-
security: [{ BearerAuth: [] }],
|
|
156
|
-
requestBody: {
|
|
157
|
-
required: true,
|
|
158
|
-
content: {
|
|
159
|
-
'application/json': {
|
|
160
|
-
schema: {
|
|
161
|
-
type: 'object',
|
|
162
|
-
properties: {
|
|
163
|
-
model: { type: 'string' },
|
|
164
|
-
prompt: { type: 'string' },
|
|
165
|
-
max_tokens: { type: 'integer' },
|
|
166
|
-
stream: { type: 'boolean', default:
|
|
167
|
-
},
|
|
168
|
-
required: ['model', 'prompt'],
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
responses: {
|
|
174
|
-
200: { description: 'Completion response' },
|
|
175
|
-
429: { description: 'Rate limit exceeded' },
|
|
176
|
-
},
|
|
177
|
-
},
|
|
178
|
-
},
|
|
179
|
-
'/ai-llm/v1/embeddings': {
|
|
180
|
-
post: {
|
|
181
|
-
tags: ['ai-llm'],
|
|
182
|
-
summary: 'Generate embeddings',
|
|
183
|
-
description: 'OpenAI-compatible embeddings endpoint.',
|
|
184
|
-
security: [{ BearerAuth: [] }],
|
|
185
|
-
requestBody: {
|
|
186
|
-
required: true,
|
|
187
|
-
content: {
|
|
188
|
-
'application/json': {
|
|
189
|
-
schema: {
|
|
190
|
-
type: 'object',
|
|
191
|
-
properties: {
|
|
192
|
-
model: { type: 'string', example: 'openai/text-embedding-ada-002' },
|
|
193
|
-
input: {
|
|
194
|
-
oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }],
|
|
195
|
-
},
|
|
196
|
-
},
|
|
197
|
-
required: ['model', 'input'],
|
|
198
|
-
},
|
|
199
|
-
},
|
|
200
|
-
},
|
|
201
|
-
},
|
|
202
|
-
responses: {
|
|
203
|
-
200: {
|
|
204
|
-
description: 'Embedding vectors',
|
|
205
|
-
content: {
|
|
206
|
-
'application/json': {
|
|
207
|
-
schema: {
|
|
208
|
-
type: 'object',
|
|
209
|
-
properties: {
|
|
210
|
-
object: { type: 'string', example: 'list' },
|
|
211
|
-
data: {
|
|
212
|
-
type: 'array',
|
|
213
|
-
items: {
|
|
214
|
-
type: 'object',
|
|
215
|
-
properties: {
|
|
216
|
-
object: { type: 'string', example: 'embedding' },
|
|
217
|
-
embedding: { type: 'array', items: { type: 'number' } },
|
|
218
|
-
index: { type: 'integer' },
|
|
219
|
-
},
|
|
220
|
-
},
|
|
221
|
-
},
|
|
222
|
-
model: { type: 'string' },
|
|
223
|
-
usage: {
|
|
224
|
-
type: 'object',
|
|
225
|
-
properties: {
|
|
226
|
-
prompt_tokens: { type: 'integer' },
|
|
227
|
-
total_tokens: { type: 'integer' },
|
|
228
|
-
},
|
|
229
|
-
},
|
|
230
|
-
},
|
|
231
|
-
},
|
|
232
|
-
},
|
|
233
|
-
},
|
|
234
|
-
},
|
|
235
|
-
429: { description: 'Rate limit exceeded' },
|
|
236
|
-
},
|
|
237
|
-
},
|
|
238
|
-
},
|
|
239
|
-
},
|
|
240
|
-
components: {
|
|
241
|
-
schemas: {
|
|
242
|
-
AiApiConfig: {
|
|
243
|
-
type: 'object',
|
|
244
|
-
properties: {
|
|
245
|
-
mode: {
|
|
246
|
-
type: 'string',
|
|
247
|
-
enum: ['llm', 'agent'],
|
|
248
|
-
description: 'Default AI mode',
|
|
249
|
-
},
|
|
250
|
-
defaultAiEmployee: { type: 'string', description: 'Default AI employee name' },
|
|
251
|
-
defaultLlmService: { type: 'string', description: 'Default LLM service name' },
|
|
252
|
-
enabledLlmServices: {
|
|
253
|
-
type: 'array',
|
|
254
|
-
items: { type: 'string' },
|
|
255
|
-
description: 'List of enabled LLM service names',
|
|
256
|
-
},
|
|
257
|
-
rateLimitPerMinute: {
|
|
258
|
-
type: 'integer',
|
|
259
|
-
description: 'Max requests per minute per user (0 = unlimited)',
|
|
260
|
-
},
|
|
261
|
-
},
|
|
262
|
-
},
|
|
263
|
-
ModelObject: {
|
|
264
|
-
type: 'object',
|
|
265
|
-
properties: {
|
|
266
|
-
id: { type: 'string', example: 'openai/gpt-4o', description: 'Model ID (serviceName/modelId)' },
|
|
267
|
-
object: { type: 'string', example: 'model' },
|
|
268
|
-
created: { type: 'integer' },
|
|
269
|
-
owned_by: { type: 'string' },
|
|
270
|
-
},
|
|
271
|
-
},
|
|
272
|
-
ChatMessage: {
|
|
273
|
-
type: 'object',
|
|
274
|
-
properties: {
|
|
275
|
-
role: { type: 'string', enum: ['system', 'user', 'assistant', 'tool'] },
|
|
276
|
-
content: { type: 'string' },
|
|
277
|
-
name: { type: 'string' },
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
info: {
|
|
12
|
+
title: 'NocoBase API - AI API Plugin',
|
|
13
|
+
description: 'OpenAI-compatible AI gateway and configuration API',
|
|
14
|
+
},
|
|
15
|
+
tags: [
|
|
16
|
+
{ name: 'aiApiConfig', description: 'AI API configuration management' },
|
|
17
|
+
{ name: 'ai-llm', description: 'OpenAI-compatible LLM gateway (prefix: /api/ai-llm/v1)' },
|
|
18
|
+
],
|
|
19
|
+
paths: {
|
|
20
|
+
'/aiApiConfig:get': {
|
|
21
|
+
get: {
|
|
22
|
+
tags: ['aiApiConfig'],
|
|
23
|
+
summary: 'Get AI API configuration',
|
|
24
|
+
security: [{ BearerAuth: [] }],
|
|
25
|
+
responses: {
|
|
26
|
+
200: {
|
|
27
|
+
description: 'Current AI API configuration',
|
|
28
|
+
content: {
|
|
29
|
+
'application/json': {
|
|
30
|
+
schema: { $ref: '#/components/schemas/AiApiConfig' },
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
'/aiApiConfig:save': {
|
|
38
|
+
post: {
|
|
39
|
+
tags: ['aiApiConfig'],
|
|
40
|
+
summary: 'Save AI API configuration',
|
|
41
|
+
security: [{ BearerAuth: [] }],
|
|
42
|
+
requestBody: {
|
|
43
|
+
required: true,
|
|
44
|
+
content: {
|
|
45
|
+
'application/json': {
|
|
46
|
+
schema: { $ref: '#/components/schemas/AiApiConfig' },
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
responses: {
|
|
51
|
+
200: { description: 'Configuration saved successfully' },
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
'/ai-llm/v1/models': {
|
|
56
|
+
get: {
|
|
57
|
+
tags: ['ai-llm'],
|
|
58
|
+
summary: 'List available models',
|
|
59
|
+
description:
|
|
60
|
+
'Returns all LLM models available across registered services. Model IDs are formatted as `serviceName/modelId`.',
|
|
61
|
+
security: [{ BearerAuth: [] }],
|
|
62
|
+
responses: {
|
|
63
|
+
200: {
|
|
64
|
+
description: 'List of available models',
|
|
65
|
+
content: {
|
|
66
|
+
'application/json': {
|
|
67
|
+
schema: {
|
|
68
|
+
type: 'object',
|
|
69
|
+
properties: {
|
|
70
|
+
object: { type: 'string', example: 'list' },
|
|
71
|
+
data: {
|
|
72
|
+
type: 'array',
|
|
73
|
+
items: { $ref: '#/components/schemas/ModelObject' },
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
'/ai-llm/v1/models/{id}': {
|
|
84
|
+
get: {
|
|
85
|
+
tags: ['ai-llm'],
|
|
86
|
+
summary: 'Get model details',
|
|
87
|
+
security: [{ BearerAuth: [] }],
|
|
88
|
+
parameters: [
|
|
89
|
+
{
|
|
90
|
+
name: 'id',
|
|
91
|
+
in: 'path',
|
|
92
|
+
required: true,
|
|
93
|
+
description: 'Model ID in format `serviceName/modelId`',
|
|
94
|
+
schema: { type: 'string', example: 'openai/gpt-4o' },
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
responses: {
|
|
98
|
+
200: {
|
|
99
|
+
description: 'Model details',
|
|
100
|
+
content: {
|
|
101
|
+
'application/json': {
|
|
102
|
+
schema: { $ref: '#/components/schemas/ModelObject' },
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
404: { description: 'Model not found' },
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
'/ai-llm/v1/chat/completions': {
|
|
111
|
+
post: {
|
|
112
|
+
tags: ['ai-llm'],
|
|
113
|
+
summary: 'Chat completions',
|
|
114
|
+
description:
|
|
115
|
+
'OpenAI-compatible chat completions endpoint. Supports streaming (`stream: true`). Use header `X-AI-Mode: llm` (default) or `X-AI-Mode: agent` to switch between direct LLM and agent mode.',
|
|
116
|
+
security: [{ BearerAuth: [] }],
|
|
117
|
+
parameters: [
|
|
118
|
+
{
|
|
119
|
+
name: 'X-AI-Mode',
|
|
120
|
+
in: 'header',
|
|
121
|
+
required: false,
|
|
122
|
+
description: 'AI mode: `llm` (default) or `agent`',
|
|
123
|
+
schema: { type: 'string', enum: ['llm', 'agent'], default: 'llm' },
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
requestBody: {
|
|
127
|
+
required: true,
|
|
128
|
+
content: {
|
|
129
|
+
'application/json': {
|
|
130
|
+
schema: { $ref: '#/components/schemas/ChatCompletionRequest' },
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
responses: {
|
|
135
|
+
200: {
|
|
136
|
+
description: 'Chat completion response (or SSE stream when `stream: true`)',
|
|
137
|
+
content: {
|
|
138
|
+
'application/json': {
|
|
139
|
+
schema: { $ref: '#/components/schemas/ChatCompletionResponse' },
|
|
140
|
+
},
|
|
141
|
+
'text/event-stream': {
|
|
142
|
+
schema: { type: 'string', description: 'SSE stream of completion chunks' },
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
429: { description: 'Rate limit exceeded' },
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
'/ai-llm/v1/completions': {
|
|
151
|
+
post: {
|
|
152
|
+
tags: ['ai-llm'],
|
|
153
|
+
summary: 'Text completions (legacy)',
|
|
154
|
+
description: 'Legacy text completions for LiteLLM compatibility.',
|
|
155
|
+
security: [{ BearerAuth: [] }],
|
|
156
|
+
requestBody: {
|
|
157
|
+
required: true,
|
|
158
|
+
content: {
|
|
159
|
+
'application/json': {
|
|
160
|
+
schema: {
|
|
161
|
+
type: 'object',
|
|
162
|
+
properties: {
|
|
163
|
+
model: { type: 'string' },
|
|
164
|
+
prompt: { type: 'string' },
|
|
165
|
+
max_tokens: { type: 'integer' },
|
|
166
|
+
stream: { type: 'boolean', default: true },
|
|
167
|
+
},
|
|
168
|
+
required: ['model', 'prompt'],
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
responses: {
|
|
174
|
+
200: { description: 'Completion response' },
|
|
175
|
+
429: { description: 'Rate limit exceeded' },
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
'/ai-llm/v1/embeddings': {
|
|
180
|
+
post: {
|
|
181
|
+
tags: ['ai-llm'],
|
|
182
|
+
summary: 'Generate embeddings',
|
|
183
|
+
description: 'OpenAI-compatible embeddings endpoint.',
|
|
184
|
+
security: [{ BearerAuth: [] }],
|
|
185
|
+
requestBody: {
|
|
186
|
+
required: true,
|
|
187
|
+
content: {
|
|
188
|
+
'application/json': {
|
|
189
|
+
schema: {
|
|
190
|
+
type: 'object',
|
|
191
|
+
properties: {
|
|
192
|
+
model: { type: 'string', example: 'openai/text-embedding-ada-002' },
|
|
193
|
+
input: {
|
|
194
|
+
oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }],
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
required: ['model', 'input'],
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
responses: {
|
|
203
|
+
200: {
|
|
204
|
+
description: 'Embedding vectors',
|
|
205
|
+
content: {
|
|
206
|
+
'application/json': {
|
|
207
|
+
schema: {
|
|
208
|
+
type: 'object',
|
|
209
|
+
properties: {
|
|
210
|
+
object: { type: 'string', example: 'list' },
|
|
211
|
+
data: {
|
|
212
|
+
type: 'array',
|
|
213
|
+
items: {
|
|
214
|
+
type: 'object',
|
|
215
|
+
properties: {
|
|
216
|
+
object: { type: 'string', example: 'embedding' },
|
|
217
|
+
embedding: { type: 'array', items: { type: 'number' } },
|
|
218
|
+
index: { type: 'integer' },
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
model: { type: 'string' },
|
|
223
|
+
usage: {
|
|
224
|
+
type: 'object',
|
|
225
|
+
properties: {
|
|
226
|
+
prompt_tokens: { type: 'integer' },
|
|
227
|
+
total_tokens: { type: 'integer' },
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
429: { description: 'Rate limit exceeded' },
|
|
236
|
+
},
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
components: {
|
|
241
|
+
schemas: {
|
|
242
|
+
AiApiConfig: {
|
|
243
|
+
type: 'object',
|
|
244
|
+
properties: {
|
|
245
|
+
mode: {
|
|
246
|
+
type: 'string',
|
|
247
|
+
enum: ['llm', 'agent'],
|
|
248
|
+
description: 'Default AI mode',
|
|
249
|
+
},
|
|
250
|
+
defaultAiEmployee: { type: 'string', description: 'Default AI employee name' },
|
|
251
|
+
defaultLlmService: { type: 'string', description: 'Default LLM service name' },
|
|
252
|
+
enabledLlmServices: {
|
|
253
|
+
type: 'array',
|
|
254
|
+
items: { type: 'string' },
|
|
255
|
+
description: 'List of enabled LLM service names',
|
|
256
|
+
},
|
|
257
|
+
rateLimitPerMinute: {
|
|
258
|
+
type: 'integer',
|
|
259
|
+
description: 'Max requests per minute per user (0 = unlimited)',
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
ModelObject: {
|
|
264
|
+
type: 'object',
|
|
265
|
+
properties: {
|
|
266
|
+
id: { type: 'string', example: 'openai/gpt-4o', description: 'Model ID (serviceName/modelId)' },
|
|
267
|
+
object: { type: 'string', example: 'model' },
|
|
268
|
+
created: { type: 'integer' },
|
|
269
|
+
owned_by: { type: 'string' },
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
ChatMessage: {
|
|
273
|
+
type: 'object',
|
|
274
|
+
properties: {
|
|
275
|
+
role: { type: 'string', enum: ['system', 'user', 'assistant', 'tool'] },
|
|
276
|
+
content: { type: 'string' },
|
|
277
|
+
name: { type: 'string' },
|
|
278
|
+
tool_call_id: { type: 'string' },
|
|
279
|
+
tool_calls: { type: 'array', items: { $ref: '#/components/schemas/ToolCall' } },
|
|
280
|
+
},
|
|
281
|
+
required: ['role', 'content'],
|
|
282
|
+
},
|
|
283
|
+
ChatCompletionRequest: {
|
|
284
|
+
type: 'object',
|
|
285
|
+
properties: {
|
|
286
|
+
model: { type: 'string', example: 'openai/gpt-4o' },
|
|
287
|
+
messages: { type: 'array', items: { $ref: '#/components/schemas/ChatMessage' } },
|
|
288
|
+
stream: { type: 'boolean', default: true },
|
|
289
|
+
temperature: { type: 'number', minimum: 0, maximum: 2 },
|
|
290
|
+
max_tokens: { type: 'integer' },
|
|
291
|
+
top_p: { type: 'number' },
|
|
292
|
+
frequency_penalty: { type: 'number' },
|
|
293
|
+
presence_penalty: { type: 'number' },
|
|
294
|
+
tools: { type: 'array', items: { $ref: '#/components/schemas/ToolDefinition' } },
|
|
295
|
+
tool_choice: {
|
|
296
|
+
description: 'OpenAI-compatible tool choice: auto, none, required, or a named function choice.',
|
|
297
|
+
oneOf: [{ type: 'string', enum: ['auto', 'none', 'required'] }, { type: 'object' }],
|
|
298
|
+
},
|
|
299
|
+
},
|
|
300
|
+
required: ['model', 'messages'],
|
|
301
|
+
},
|
|
302
|
+
ChatCompletionResponse: {
|
|
303
|
+
type: 'object',
|
|
304
|
+
properties: {
|
|
305
|
+
id: { type: 'string' },
|
|
306
|
+
object: { type: 'string', example: 'chat.completion' },
|
|
307
|
+
created: { type: 'integer' },
|
|
308
|
+
model: { type: 'string' },
|
|
309
|
+
choices: {
|
|
310
|
+
type: 'array',
|
|
311
|
+
items: {
|
|
312
|
+
type: 'object',
|
|
313
|
+
properties: {
|
|
314
|
+
index: { type: 'integer' },
|
|
315
|
+
message: { $ref: '#/components/schemas/ChatMessage' },
|
|
316
|
+
finish_reason: { type: 'string', enum: ['stop', 'length', 'tool_calls'] },
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
},
|
|
320
|
+
usage: {
|
|
321
|
+
type: 'object',
|
|
322
|
+
properties: {
|
|
323
|
+
prompt_tokens: { type: 'integer' },
|
|
324
|
+
completion_tokens: { type: 'integer' },
|
|
325
|
+
total_tokens: { type: 'integer' },
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
ToolDefinition: {
|
|
331
|
+
type: 'object',
|
|
332
|
+
properties: {
|
|
333
|
+
type: { type: 'string', enum: ['function'] },
|
|
334
|
+
function: {
|
|
335
|
+
type: 'object',
|
|
336
|
+
properties: {
|
|
337
|
+
name: { type: 'string' },
|
|
338
|
+
description: { type: 'string' },
|
|
339
|
+
parameters: { type: 'object' },
|
|
340
|
+
},
|
|
341
|
+
required: ['name', 'parameters'],
|
|
342
|
+
},
|
|
343
|
+
},
|
|
344
|
+
required: ['type', 'function'],
|
|
345
|
+
},
|
|
346
|
+
ToolCall: {
|
|
347
|
+
type: 'object',
|
|
348
|
+
properties: {
|
|
349
|
+
id: { type: 'string' },
|
|
350
|
+
type: { type: 'string', enum: ['function'] },
|
|
351
|
+
function: {
|
|
352
|
+
type: 'object',
|
|
353
|
+
properties: { name: { type: 'string' }, arguments: { type: 'string' } },
|
|
354
|
+
},
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
},
|
|
359
|
+
};
|