@aalis/api-llm 0.13.0 → 0.14.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/index.d.ts +97 -35
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +115 -23
- package/dist/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ToolDefinition } from '@aalis/api-tools';
|
|
2
|
-
import type {
|
|
2
|
+
import type { Events, ProviderEntry, ServiceSelection } from '@aalis/core';
|
|
3
3
|
import type { Message, ToolCall } from '@aalis/schema-message';
|
|
4
4
|
export interface ChatResponse {
|
|
5
5
|
content: string | null;
|
|
@@ -21,7 +21,7 @@ export interface ChatResponse {
|
|
|
21
21
|
}
|
|
22
22
|
/**
|
|
23
23
|
* 工具调用增量进度(非完整 ToolCall,仅用于 UI 提示「正在生成」)。
|
|
24
|
-
* Provider
|
|
24
|
+
* Provider 每收到一个调用的增量就为它 yield 一个 chunk(一帧里有几个调用就各 yield 一个),
|
|
25
25
|
* 让上层可以渲染进度条而不必等整段 tool_calls 累积完。
|
|
26
26
|
*/
|
|
27
27
|
export interface ToolCallProgress {
|
|
@@ -47,17 +47,6 @@ export interface ChatStreamChunk {
|
|
|
47
47
|
cachedPromptTokens?: number;
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
|
-
export interface ModelInfo {
|
|
51
|
-
id: string;
|
|
52
|
-
/**
|
|
53
|
-
* Capability 字符串数组,取自 model handle 的 `instance.capabilities` 元数据。使用宽松的 string[]
|
|
54
|
-
* 而不是 LLMCapability[],便于跨插件共享(自定义 capability 也能照常上送给前端)。
|
|
55
|
-
*/
|
|
56
|
-
capabilities: string[];
|
|
57
|
-
provider?: string;
|
|
58
|
-
contextId?: string;
|
|
59
|
-
contextLength?: number;
|
|
60
|
-
}
|
|
61
50
|
/** Per-model chat request:不再含 model/provider —— entry 已绑定。 */
|
|
62
51
|
export interface ChatModelRequest {
|
|
63
52
|
messages: Message[];
|
|
@@ -65,7 +54,11 @@ export interface ChatModelRequest {
|
|
|
65
54
|
temperature?: number;
|
|
66
55
|
maxTokens?: number;
|
|
67
56
|
signal?: AbortSignal;
|
|
68
|
-
|
|
57
|
+
/**
|
|
58
|
+
* 深度思考的档位:模型声明的 {@link LLMModel.thinking} 里某一档的 id;没带时按模型的默认档。模型不能调(没声明档位)时
|
|
59
|
+
* 不带,带了模型没有的档位提供者拒绝(见 {@link requestedThinking})
|
|
60
|
+
*/
|
|
61
|
+
think?: string;
|
|
69
62
|
/**
|
|
70
63
|
* 消息里的图片是否为必需载荷。缺省 false。
|
|
71
64
|
*
|
|
@@ -78,6 +71,12 @@ export interface ChatModelRequest {
|
|
|
78
71
|
* 这个判断只有调用方做得了,provider 无从区分两种语义。
|
|
79
72
|
*/
|
|
80
73
|
requireImages?: boolean;
|
|
74
|
+
/** 这次调用做什么用,记账用:给人看的短语,如「对话」「摘要」「识图」「子任务」。调用方填,可以缺 */
|
|
75
|
+
purpose?: string;
|
|
76
|
+
/** 这次调用所在的会话,记账用。调用方填,可以缺 */
|
|
77
|
+
sessionId?: string;
|
|
78
|
+
/** 调用方的插件实例,记账用:经 `llm` 的绑定接口调用时按调用方这次激活填上,调用方自己填的不算 */
|
|
79
|
+
caller?: string;
|
|
81
80
|
}
|
|
82
81
|
/**
|
|
83
82
|
* 单个 LLM model 的 service entry。
|
|
@@ -87,10 +86,10 @@ export interface ChatModelRequest {
|
|
|
87
86
|
* model handle 上的 capabilities 字段诚实地反映该 model 的能力。
|
|
88
87
|
*
|
|
89
88
|
* 调用约定:
|
|
90
|
-
* const handle = resolveLLMModel(llm, ref, ['vision'])?.
|
|
89
|
+
* const handle = resolveLLMModel(llm, ref, ['vision'])?.use;
|
|
91
90
|
* await handle?.chat({ messages }); // entry 已知道是哪个 model
|
|
92
91
|
*
|
|
93
|
-
*
|
|
92
|
+
* 默认 model 是 llm 服务的偏好,由用户经管理面(WebUI 或宿主配置的 `servicePreferences`)设为 `<provider>/<model>`。
|
|
94
93
|
*/
|
|
95
94
|
export interface LLMModel {
|
|
96
95
|
/** model id(provider 内唯一,如 'gpt-4o')。来源:provider plugin 注册时填入。 */
|
|
@@ -111,6 +110,8 @@ export interface LLMModel {
|
|
|
111
110
|
* **不是** DI 选择机制(服务选择一律走配置 + 按名解析)。provider 注册时填。
|
|
112
111
|
*/
|
|
113
112
|
readonly capabilities: readonly LLMCapability[];
|
|
113
|
+
/** 能调深度思考的模型允许的档位;不能调的模型不声明 */
|
|
114
|
+
readonly thinking?: ThinkingLevels;
|
|
114
115
|
chat(request: ChatModelRequest): Promise<ChatResponse>;
|
|
115
116
|
chatStream?(request: ChatModelRequest): AsyncIterable<ChatStreamChunk>;
|
|
116
117
|
/**
|
|
@@ -130,12 +131,71 @@ export interface LLMModel {
|
|
|
130
131
|
removed: string[];
|
|
131
132
|
total: number;
|
|
132
133
|
}>;
|
|
134
|
+
/**
|
|
135
|
+
* 查服务商账户的余额(可选):服务商有余额接口才实现,同一 provider 下所有 model entries 共享同一份,按 providerId
|
|
136
|
+
* 找任一 entry 调一次即可。查不到(不可达、超时、认证失败、回应认不出)时抛错,消息带原因
|
|
137
|
+
*/
|
|
138
|
+
balance?(signal?: AbortSignal): Promise<LLMBalance[]>;
|
|
139
|
+
}
|
|
140
|
+
/** 服务商账户的余额:一个币种一项 */
|
|
141
|
+
export interface LLMBalance {
|
|
142
|
+
readonly currency: string;
|
|
143
|
+
readonly amount: number;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* 一次模型调用的用量,`llm:usage` 事件的内容。cachedTokens 是 inputTokens 里前缀缓存命中的部分,服务商不报时没有
|
|
147
|
+
* (与 0 不同);caller、sessionId、purpose 取请求里的同名字段
|
|
148
|
+
*/
|
|
149
|
+
export interface LLMUsageEvent {
|
|
150
|
+
/** 服务商:模型所属 provider 的实例 id({@link LLMModel.providerId}) */
|
|
151
|
+
provider: string;
|
|
152
|
+
model: string;
|
|
153
|
+
caller?: string;
|
|
154
|
+
sessionId?: string;
|
|
155
|
+
purpose?: string;
|
|
156
|
+
inputTokens: number;
|
|
157
|
+
cachedTokens?: number;
|
|
158
|
+
outputTokens: number;
|
|
159
|
+
}
|
|
160
|
+
declare module '@aalis/core' {
|
|
161
|
+
interface AalisEvents {
|
|
162
|
+
/** 一次模型调用结束、服务商报了用量:发射方是服务商登记的 {@link metered} 模型,消费方如记账插件 */
|
|
163
|
+
'llm:usage': [usage: LLMUsageEvent];
|
|
164
|
+
}
|
|
133
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* 给登记的模型包上记账:chat 拿到用量、chatStream 结束时报过用量(取最后一次报的),就发一次 `llm:usage`,不等监听器。
|
|
168
|
+
* 服务商登记模型时套一层,`provide(llm, metered(model, events), { entryId })`,自己的 chat 与 chatStream 不用管记账。
|
|
169
|
+
* 服务商回的数运行时没人核,在这里规整一次:没报用量、输入或输出不是非负有限数的调用不记;缓存命中不是非负有限数时当没报,
|
|
170
|
+
* 比输入多时截到输入
|
|
171
|
+
*/
|
|
172
|
+
export declare function metered(model: LLMModel, events: Pick<Events, 'emit'>): LLMModel;
|
|
173
|
+
/** 一个思考档位:id 是提供者自己的写法(请求的 think 填它),label 给人看 */
|
|
174
|
+
export interface ThinkingLevel {
|
|
175
|
+
readonly id: string;
|
|
176
|
+
readonly label: string;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* 模型允许的思考档位:levels 由浅到深排、至少两档(开关型就是「关、开」两档),default 是请求没带档位时用的那一档,
|
|
180
|
+
* 须是 levels 里的一个。档位由各提供者按自己的协议定义并翻成线上字段,不做跨服务商的统一档位表
|
|
181
|
+
*/
|
|
182
|
+
export interface ThinkingLevels {
|
|
183
|
+
readonly levels: readonly ThinkingLevel[];
|
|
184
|
+
readonly default: string;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* 请求带的思考档位:没带时为 undefined;带了却不在模型声明的档位里(含模型不能调时带了档位)时抛错。提供者把档位翻成
|
|
188
|
+
* 线上字段之前先过它,调用方要先按模型声明的档位选
|
|
189
|
+
*/
|
|
190
|
+
export declare function requestedThinking(model: Pick<LLMModel, 'id' | 'thinking'>, request: Pick<ChatModelRequest, 'think'>): string | undefined;
|
|
191
|
+
/** 模型最浅的一档:机械任务(摘要、标题、结构化提取)要压低思考时带它;模型不能调时为 undefined */
|
|
192
|
+
export declare function lightestThinking(model: Pick<LLMModel, 'thinking'>): string | undefined;
|
|
134
193
|
export interface LLMCapabilityRegistry {
|
|
135
194
|
Chat: 'chat';
|
|
136
195
|
ToolCalling: 'tool_calling';
|
|
137
196
|
Streaming: 'streaming';
|
|
138
197
|
Vision: 'vision';
|
|
198
|
+
/** 会思考(产出思考内容);能不能按请求调档看 {@link LLMModel.thinking} */
|
|
139
199
|
Thinking: 'thinking';
|
|
140
200
|
/** 原生音频理解(能接收音频输入,返回描述/问答,如 Gemini / GPT-4o-audio / Gemma 4 E系列) */
|
|
141
201
|
Audio: 'audio';
|
|
@@ -161,17 +221,11 @@ declare module '@aalis/schema-config' {
|
|
|
161
221
|
* LLM 模型引用:值为 {@link ModelRef},前端渲染为
|
|
162
222
|
* 联动 select(provider 列表来自 `/api/models/llm` 的 contextId 聚合;
|
|
163
223
|
* model 列表由所选 provider 决定)。运行时由消费方用
|
|
164
|
-
* `resolveLLMModel(llm, value, caps)` 解析。parseConfig 不校验这个类型的取值,除 `''`(未选)外原样透传。
|
|
224
|
+
* `resolveLLMModel(caps.llm, value, caps)` 解析。parseConfig 不校验这个类型的取值,除 `''`(未选)外原样透传。
|
|
165
225
|
*/
|
|
166
226
|
'llm-ref': ModelRef;
|
|
167
227
|
}
|
|
168
228
|
}
|
|
169
|
-
/** 一个 'llm' entry 的快照(ServiceRef.all() 所返 ServiceView 的 instance/contextId/label 子集)。 */
|
|
170
|
-
export interface LLMModelEntry {
|
|
171
|
-
instance: LLMModel;
|
|
172
|
-
contextId: string;
|
|
173
|
-
label?: string;
|
|
174
|
-
}
|
|
175
229
|
/**
|
|
176
230
|
* LLM model 引用:`{ provider, model }` 二元组。
|
|
177
231
|
* 由 ConfigSchema type='llm-ref' 字段统一编辑,YAML 中以嵌套对象形式存储。
|
|
@@ -183,23 +237,31 @@ export interface ModelRef {
|
|
|
183
237
|
model?: string;
|
|
184
238
|
}
|
|
185
239
|
/**
|
|
186
|
-
*
|
|
187
|
-
*
|
|
240
|
+
* 按能力过滤 llm 的提供者条目 —— 能力源为模型自带的元数据 `use.capabilities`,
|
|
241
|
+
* 不是 core 的能力选择(服务选择走配置 + 按名解析)。
|
|
188
242
|
*/
|
|
189
|
-
|
|
243
|
+
/**
|
|
244
|
+
* 列出(可按能力过滤的)llm 提供者条目,供 `/model` 列表与前端下拉用。
|
|
245
|
+
* 能力源为 `use.capabilities`(model 自带元数据),是展示/列举用途,非 DI 选择。
|
|
246
|
+
*/
|
|
247
|
+
export declare function listLLMModels(source: Pick<ServiceSelection<LLMModel>, 'list'>, opts?: {
|
|
190
248
|
caps?: readonly LLMCapability[];
|
|
191
|
-
}):
|
|
249
|
+
}): ProviderEntry<LLMModel>[];
|
|
192
250
|
/**
|
|
193
|
-
*
|
|
251
|
+
* 在 `list()` 上把 ref 解析为最匹配的提供者条目。
|
|
194
252
|
*
|
|
195
253
|
* 解析顺序(命中即返回):
|
|
196
|
-
* 1. ref.provider + ref.model 都有 →
|
|
197
|
-
* 2. 仅 ref.provider → 在该 provider
|
|
198
|
-
* 3. 仅 ref.model →
|
|
199
|
-
* 4. 都为空 → 取首个满足 capability
|
|
254
|
+
* 1. ref.provider + ref.model 都有 → 直接拼接条目 id `${provider}/${model}` 查找
|
|
255
|
+
* 2. 仅 ref.provider → 在该 provider 名下的条目中(按 capability 过滤后)取首个
|
|
256
|
+
* 3. 仅 ref.model → 按模型自己的 `use.id` 严格匹配
|
|
257
|
+
* 4. 都为空 → 取首个满足 capability 的条目(本插件选中的那一家在前,其余按挑选规则排)
|
|
200
258
|
*
|
|
201
|
-
* requiredCaps
|
|
259
|
+
* requiredCaps 按模型元数据 `use.capabilities` 过滤。找不到返回 undefined。
|
|
260
|
+
*/
|
|
261
|
+
export declare function resolveLLMModel(source: Pick<ServiceSelection<LLMModel>, 'list'>, ref?: ModelRef | null, requiredCaps?: LLMCapability[]): ProviderEntry<LLMModel> | undefined;
|
|
262
|
+
/**
|
|
263
|
+
* 调用型。业务层在请求里填上调用方这次激活的实例 id({@link ChatModelRequest.caller}),其余成员照原样转发。
|
|
264
|
+
* 按模型选就是按条目 id 选:`caps.llm.of('<provider>/<model>')`;按能力筛遍历 `caps.llm.list()`,读条目的 `use.capabilities`
|
|
202
265
|
*/
|
|
203
|
-
export declare
|
|
204
|
-
export declare const llm: import("@aalis/core").ServiceDescriptor<LLMModel, ServiceRef<LLMModel>>;
|
|
266
|
+
export declare const llm: import("@aalis/core").ServiceDescriptor<LLMModel, LLMModel>;
|
|
205
267
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,86 @@
|
|
|
3
3
|
// 提供完整的 LLM 抽象 + 能力声明框架。
|
|
4
4
|
// 任何需要调用或实现 LLM 服务的插件都应从本包导入相关类型。
|
|
5
5
|
import { defineService } from '@aalis/core';
|
|
6
|
+
/**
|
|
7
|
+
* 换掉 chat 与 chatStream,其余字段与方法照原样转给 model。逐个字段列出,LLMModel 加了字段这里漏写时编译报错
|
|
8
|
+
* (chatStream 要写出来,没有时是 undefined)
|
|
9
|
+
*/
|
|
10
|
+
function withCalls(model, calls) {
|
|
11
|
+
const refresh = model.refresh?.bind(model);
|
|
12
|
+
const balance = model.balance?.bind(model);
|
|
13
|
+
return {
|
|
14
|
+
id: model.id,
|
|
15
|
+
providerId: model.providerId,
|
|
16
|
+
contextLength: model.contextLength,
|
|
17
|
+
maxOutputTokens: model.maxOutputTokens,
|
|
18
|
+
capabilities: model.capabilities,
|
|
19
|
+
thinking: model.thinking,
|
|
20
|
+
...calls,
|
|
21
|
+
refresh,
|
|
22
|
+
balance,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const isCount = (value) => typeof value === 'number' && Number.isFinite(value) && value >= 0;
|
|
26
|
+
/**
|
|
27
|
+
* 给登记的模型包上记账:chat 拿到用量、chatStream 结束时报过用量(取最后一次报的),就发一次 `llm:usage`,不等监听器。
|
|
28
|
+
* 服务商登记模型时套一层,`provide(llm, metered(model, events), { entryId })`,自己的 chat 与 chatStream 不用管记账。
|
|
29
|
+
* 服务商回的数运行时没人核,在这里规整一次:没报用量、输入或输出不是非负有限数的调用不记;缓存命中不是非负有限数时当没报,
|
|
30
|
+
* 比输入多时截到输入
|
|
31
|
+
*/
|
|
32
|
+
export function metered(model, events) {
|
|
33
|
+
const report = (request, usage) => {
|
|
34
|
+
if (!usage || !isCount(usage.promptTokens) || !isCount(usage.completionTokens))
|
|
35
|
+
return;
|
|
36
|
+
const cached = usage.cachedPromptTokens;
|
|
37
|
+
void events.emit('llm:usage', {
|
|
38
|
+
provider: model.providerId,
|
|
39
|
+
model: model.id,
|
|
40
|
+
caller: request.caller,
|
|
41
|
+
sessionId: request.sessionId,
|
|
42
|
+
purpose: request.purpose,
|
|
43
|
+
inputTokens: usage.promptTokens,
|
|
44
|
+
...(isCount(cached) ? { cachedTokens: Math.min(cached, usage.promptTokens) } : {}),
|
|
45
|
+
outputTokens: usage.completionTokens,
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
const { chatStream } = model;
|
|
49
|
+
return withCalls(model, {
|
|
50
|
+
async chat(request) {
|
|
51
|
+
const response = await model.chat(request);
|
|
52
|
+
report(request, response.usage);
|
|
53
|
+
return response;
|
|
54
|
+
},
|
|
55
|
+
chatStream: chatStream &&
|
|
56
|
+
async function* (request) {
|
|
57
|
+
let usage;
|
|
58
|
+
try {
|
|
59
|
+
for await (const chunk of chatStream.call(model, request)) {
|
|
60
|
+
if (chunk.usage)
|
|
61
|
+
usage = chunk.usage;
|
|
62
|
+
yield chunk;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
report(request, usage);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 请求带的思考档位:没带时为 undefined;带了却不在模型声明的档位里(含模型不能调时带了档位)时抛错。提供者把档位翻成
|
|
73
|
+
* 线上字段之前先过它,调用方要先按模型声明的档位选
|
|
74
|
+
*/
|
|
75
|
+
export function requestedThinking(model, request) {
|
|
76
|
+
const { think } = request;
|
|
77
|
+
if (think !== undefined && !model.thinking?.levels.some(level => level.id === think)) {
|
|
78
|
+
throw new Error(`模型 ${model.id} 没有思考档位「${think}」`);
|
|
79
|
+
}
|
|
80
|
+
return think;
|
|
81
|
+
}
|
|
82
|
+
/** 模型最浅的一档:机械任务(摘要、标题、结构化提取)要压低思考时带它;模型不能调时为 undefined */
|
|
83
|
+
export function lightestThinking(model) {
|
|
84
|
+
return model.thinking?.levels[0]?.id;
|
|
85
|
+
}
|
|
6
86
|
export const LLMCapabilities = {
|
|
7
87
|
Chat: 'chat',
|
|
8
88
|
ToolCalling: 'tool_calling',
|
|
@@ -14,43 +94,55 @@ export const LLMCapabilities = {
|
|
|
14
94
|
Video: 'video',
|
|
15
95
|
};
|
|
16
96
|
/**
|
|
17
|
-
* 按能力过滤
|
|
18
|
-
*
|
|
97
|
+
* 按能力过滤 llm 的提供者条目 —— 能力源为模型自带的元数据 `use.capabilities`,
|
|
98
|
+
* 不是 core 的能力选择(服务选择走配置 + 按名解析)。
|
|
19
99
|
*/
|
|
20
|
-
function listLLMEntries(source, caps) {
|
|
21
|
-
const all = source.all();
|
|
22
|
-
if (!caps || caps.length === 0)
|
|
23
|
-
return all;
|
|
24
|
-
return all.filter(e => caps.every(c => (e.instance.capabilities ?? []).includes(c)));
|
|
25
|
-
}
|
|
26
100
|
/**
|
|
27
|
-
* 列出(可按能力过滤的)
|
|
28
|
-
* 能力源为 `
|
|
101
|
+
* 列出(可按能力过滤的)llm 提供者条目,供 `/model` 列表与前端下拉用。
|
|
102
|
+
* 能力源为 `use.capabilities`(model 自带元数据),是展示/列举用途,非 DI 选择。
|
|
29
103
|
*/
|
|
30
104
|
export function listLLMModels(source, opts) {
|
|
31
|
-
|
|
105
|
+
const all = source.list();
|
|
106
|
+
const caps = opts?.caps;
|
|
107
|
+
if (!caps || caps.length === 0)
|
|
108
|
+
return all;
|
|
109
|
+
return all.filter(e => caps.every(c => (e.use.capabilities ?? []).includes(c)));
|
|
32
110
|
}
|
|
33
111
|
/**
|
|
34
|
-
*
|
|
112
|
+
* 在 `list()` 上把 ref 解析为最匹配的提供者条目。
|
|
35
113
|
*
|
|
36
114
|
* 解析顺序(命中即返回):
|
|
37
|
-
* 1. ref.provider + ref.model 都有 →
|
|
38
|
-
* 2. 仅 ref.provider → 在该 provider
|
|
39
|
-
* 3. 仅 ref.model →
|
|
40
|
-
* 4. 都为空 → 取首个满足 capability
|
|
115
|
+
* 1. ref.provider + ref.model 都有 → 直接拼接条目 id `${provider}/${model}` 查找
|
|
116
|
+
* 2. 仅 ref.provider → 在该 provider 名下的条目中(按 capability 过滤后)取首个
|
|
117
|
+
* 3. 仅 ref.model → 按模型自己的 `use.id` 严格匹配
|
|
118
|
+
* 4. 都为空 → 取首个满足 capability 的条目(本插件选中的那一家在前,其余按挑选规则排)
|
|
41
119
|
*
|
|
42
|
-
* requiredCaps
|
|
120
|
+
* requiredCaps 按模型元数据 `use.capabilities` 过滤。找不到返回 undefined。
|
|
43
121
|
*/
|
|
44
122
|
export function resolveLLMModel(source, ref, requiredCaps) {
|
|
45
|
-
const all =
|
|
123
|
+
const all = listLLMModels(source, { caps: requiredCaps });
|
|
46
124
|
if (ref?.provider && ref?.model)
|
|
47
|
-
return all.find(e => e.
|
|
125
|
+
return all.find(e => e.id === `${ref.provider}/${ref.model}`);
|
|
48
126
|
if (ref?.provider)
|
|
49
|
-
return all.find(e => e.
|
|
127
|
+
return all.find(e => e.id.startsWith(`${ref.provider}/`));
|
|
50
128
|
if (ref?.model)
|
|
51
|
-
return all.find(e => e.
|
|
129
|
+
return all.find(e => e.use.id === ref.model);
|
|
52
130
|
return all[0];
|
|
53
131
|
}
|
|
54
|
-
// -----
|
|
55
|
-
|
|
132
|
+
// ----- 服务描述符(按激活绑定)-----
|
|
133
|
+
/**
|
|
134
|
+
* 调用型。业务层在请求里填上调用方这次激活的实例 id({@link ChatModelRequest.caller}),其余成员照原样转发。
|
|
135
|
+
* 按模型选就是按条目 id 选:`caps.llm.of('<provider>/<model>')`;按能力筛遍历 `caps.llm.list()`,读条目的 `use.capabilities`
|
|
136
|
+
*/
|
|
137
|
+
export const llm = defineService('llm', port =>
|
|
138
|
+
// chatStream 是可选成员:取的时候才看选中的那一家有没有
|
|
139
|
+
Object.create(port.provider, {
|
|
140
|
+
chat: { value: (request) => port.provider.chat({ ...request, caller: port.id }) },
|
|
141
|
+
chatStream: {
|
|
142
|
+
get: () => {
|
|
143
|
+
const chatStream = port.provider.chatStream;
|
|
144
|
+
return chatStream && ((request) => chatStream({ ...request, caller: port.id }));
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
}));
|
|
56
148
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uBAAuB;AACvB,EAAE;AACF,yBAAyB;AACzB,kCAAkC;AAIlC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aalis/api-llm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -19,17 +19,17 @@
|
|
|
19
19
|
"dist"
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@aalis/schema-message": ">=0.
|
|
23
|
-
"@aalis/api-tools": ">=0.
|
|
24
|
-
"@aalis/schema-config": ">=0.
|
|
22
|
+
"@aalis/schema-message": ">=0.10.0 <1.0.0",
|
|
23
|
+
"@aalis/api-tools": ">=0.11.0 <1.0.0",
|
|
24
|
+
"@aalis/schema-config": ">=0.15.0 <1.0.0"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^22.0.0",
|
|
28
28
|
"typescript": "^5.7.0",
|
|
29
|
-
"@aalis/core": "0.
|
|
29
|
+
"@aalis/core": "0.20.0"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@aalis/core": ">=0.
|
|
32
|
+
"@aalis/core": ">=0.20.0 <1.0.0"
|
|
33
33
|
},
|
|
34
34
|
"keywords": [
|
|
35
35
|
"aalis",
|