@keo-ai/axiom 0.2.3 → 0.2.6
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 +26 -4
- package/dist/embedding_search/embed.d.ts +5 -0
- package/dist/embedding_search/embed.js +48 -15
- package/dist/embedding_search/index.d.ts +24 -1
- package/dist/embedding_search/index.js +33 -3
- package/dist/index.d.ts +10 -2
- package/dist/index.js +10 -3
- package/dist/llm_provider/bailian.js +12 -2
- package/dist/llm_provider/types.d.ts +2 -0
- package/dist/predict/predict.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -926,16 +926,16 @@ const multi = await EmbeddingSearch.query('query', {
|
|
|
926
926
|
|
|
927
927
|
### 生成 Embedding
|
|
928
928
|
|
|
929
|
-
如果你只需要把文本转成向量,直接用 `embed`:
|
|
929
|
+
如果你只需要把文本转成向量,直接用 `EmbeddingSearch.embed`:
|
|
930
930
|
|
|
931
931
|
```ts
|
|
932
|
-
import {
|
|
932
|
+
import { EmbeddingSearch } from '@keo-ai/axiom';
|
|
933
933
|
|
|
934
|
-
const vector = await embed('衣服质量怎么样');
|
|
934
|
+
const vector = await EmbeddingSearch.embed('衣服质量怎么样');
|
|
935
935
|
// vector: number[],默认 1024 维
|
|
936
936
|
|
|
937
937
|
// 指定维度(1 ~ 1024)
|
|
938
|
-
const vector256 = await embed('衣服质量怎么样', 256);
|
|
938
|
+
const vector256 = await EmbeddingSearch.embed('衣服质量怎么样', 256);
|
|
939
939
|
```
|
|
940
940
|
|
|
941
941
|
| 参数 | 类型 | 默认值 | 说明 |
|
|
@@ -943,6 +943,28 @@ const vector256 = await embed('衣服质量怎么样', 256);
|
|
|
943
943
|
| `text` | `string` | — | 要转成向量的文本(必填) |
|
|
944
944
|
| `dimensions` | `number` | `1024` | 输出维度(1 ~ 1024) |
|
|
945
945
|
|
|
946
|
+
### 批量生成 Embedding
|
|
947
|
+
|
|
948
|
+
需要一次性把多篇文本转成向量时,使用 `EmbeddingSearch.batchEmbed`:
|
|
949
|
+
|
|
950
|
+
```ts
|
|
951
|
+
import { EmbeddingSearch } from '@keo-ai/axiom';
|
|
952
|
+
|
|
953
|
+
const texts = ['衣服质量怎么样', '物流速度快吗', '售后服务如何'];
|
|
954
|
+
const vectors = await EmbeddingSearch.batchEmbed(texts);
|
|
955
|
+
// vectors: number[][],顺序与输入文本一致
|
|
956
|
+
|
|
957
|
+
// 指定维度
|
|
958
|
+
const vectors256 = await EmbeddingSearch.batchEmbed(texts, 256);
|
|
959
|
+
```
|
|
960
|
+
|
|
961
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
962
|
+
|---|---|---|---|
|
|
963
|
+
| `texts` | `string[]` | — | 要转成向量的文本数组(必填) |
|
|
964
|
+
| `dimensions` | `number` | `1024` | 输出维度(1 ~ 1024) |
|
|
965
|
+
|
|
966
|
+
> ⚠️ `EmbeddingSearch.batchEmbed` 单次最多支持 **25 条**文本(DashScope 兼容接口限制)。超过此数量请先自行分批。返回向量的顺序与输入顺序一致。
|
|
967
|
+
|
|
946
968
|
### 纯向量检索(已有向量)
|
|
947
969
|
|
|
948
970
|
`EmbeddingSearch.query` 会自动把文本转成向量并做 rerank。如果你**已经有了向量**(比如自己生成的 embedding),只想做最原始的 pgvector 近邻搜索,用 `EmbeddingSearch.vectorSearch`:
|
|
@@ -10,29 +10,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.embed = embed;
|
|
13
|
+
exports.embedBatch = embedBatch;
|
|
13
14
|
const EMBEDDING_URL = 'https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings';
|
|
14
15
|
const EMBEDDING_MODEL = 'text-embedding-v4';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
dimensions,
|
|
26
|
-
};
|
|
16
|
+
const BATCH_SIZE_LIMIT = 25; // DashScope 兼容接口的单次上限
|
|
17
|
+
function getApiKey() {
|
|
18
|
+
const apiKey = process.env.BAILIAN_API_KEY;
|
|
19
|
+
if (!apiKey) {
|
|
20
|
+
throw new Error('BAILIAN_API_KEY environment variable is not set');
|
|
21
|
+
}
|
|
22
|
+
return apiKey;
|
|
23
|
+
}
|
|
24
|
+
function fetchEmbeddings(input, dimensions) {
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
26
|
let response;
|
|
28
27
|
try {
|
|
29
28
|
response = yield fetch(EMBEDDING_URL, {
|
|
30
29
|
method: 'POST',
|
|
31
30
|
headers: {
|
|
32
31
|
'Content-Type': 'application/json',
|
|
33
|
-
Authorization: `Bearer ${
|
|
32
|
+
Authorization: `Bearer ${getApiKey()}`,
|
|
34
33
|
},
|
|
35
|
-
body: JSON.stringify(
|
|
34
|
+
body: JSON.stringify({
|
|
35
|
+
model: EMBEDDING_MODEL,
|
|
36
|
+
input,
|
|
37
|
+
dimensions,
|
|
38
|
+
}),
|
|
36
39
|
});
|
|
37
40
|
}
|
|
38
41
|
catch (cause) {
|
|
@@ -42,7 +45,13 @@ function embed(text_1) {
|
|
|
42
45
|
const text = yield response.text();
|
|
43
46
|
throw new Error(`[embedding] HTTP ${response.status}: ${text}`);
|
|
44
47
|
}
|
|
45
|
-
|
|
48
|
+
return (yield response.json());
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function embed(text_1) {
|
|
52
|
+
return __awaiter(this, arguments, void 0, function* (text, dimensions = 1024) {
|
|
53
|
+
var _a;
|
|
54
|
+
const data = yield fetchEmbeddings(text, dimensions);
|
|
46
55
|
const vector = (_a = data.data[0]) === null || _a === void 0 ? void 0 : _a.embedding;
|
|
47
56
|
if (!vector) {
|
|
48
57
|
throw new Error('[embedding] No embedding in response');
|
|
@@ -50,3 +59,27 @@ function embed(text_1) {
|
|
|
50
59
|
return vector;
|
|
51
60
|
});
|
|
52
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* 批量获取文本向量。
|
|
64
|
+
* 阿里云 DashScope 的兼容接口支持 input 为数组,但单次有数量上限。
|
|
65
|
+
*/
|
|
66
|
+
function embedBatch(texts_1) {
|
|
67
|
+
return __awaiter(this, arguments, void 0, function* (texts, dimensions = 1024) {
|
|
68
|
+
var _a;
|
|
69
|
+
if (texts.length === 0) {
|
|
70
|
+
return [];
|
|
71
|
+
}
|
|
72
|
+
if (texts.length > BATCH_SIZE_LIMIT) {
|
|
73
|
+
throw new Error(`[embedding] Batch size ${texts.length} exceeds limit ${BATCH_SIZE_LIMIT}. Split before calling.`);
|
|
74
|
+
}
|
|
75
|
+
const data = yield fetchEmbeddings(texts, dimensions);
|
|
76
|
+
// 服务返回的数据可能不是按请求顺序的,用 index 重新排序
|
|
77
|
+
const sorted = data.data.slice().sort((a, b) => a.index - b.index);
|
|
78
|
+
for (let i = 0; i < texts.length; i++) {
|
|
79
|
+
if (((_a = sorted[i]) === null || _a === void 0 ? void 0 : _a.index) !== i || !sorted[i].embedding) {
|
|
80
|
+
throw new Error(`[embedding] Missing or malformed embedding at index ${i}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return sorted.map((item) => item.embedding);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
@@ -22,6 +22,29 @@ export declare class EmbeddingSearch {
|
|
|
22
22
|
static vectorSearch(options: Omit<import('./pgvector').PgVectorSearchOptions, 'pool'> & {
|
|
23
23
|
pool: Pool;
|
|
24
24
|
}): Promise<SearchResult[]>;
|
|
25
|
+
/**
|
|
26
|
+
* 单条文本转成向量。
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* const vector = await EmbeddingSearch.embed('衣服质量怎么样');
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
static embed(text: string, dimensions?: number): Promise<number[]>;
|
|
34
|
+
/**
|
|
35
|
+
* 批量获取文本向量。
|
|
36
|
+
*
|
|
37
|
+
* 调用百炼 embedding 接口,一次最多 25 条文本。
|
|
38
|
+
* 返回向量的顺序与输入顺序一致。
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* ```ts
|
|
42
|
+
* const vectors = await EmbeddingSearch.batchEmbed([
|
|
43
|
+
* '衣服质量怎么样',
|
|
44
|
+
* '物流速度快吗',
|
|
45
|
+
* ]);
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
static batchEmbed(texts: string[], dimensions?: number): Promise<number[][]>;
|
|
25
49
|
}
|
|
26
50
|
export type { EmbeddingSearchConfig, SearchResult } from './types';
|
|
27
|
-
export { embed } from './embed';
|
|
@@ -20,7 +20,7 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
20
20
|
return t;
|
|
21
21
|
};
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
-
exports.
|
|
23
|
+
exports.EmbeddingSearch = void 0;
|
|
24
24
|
const pgvector_1 = require("./pgvector");
|
|
25
25
|
const embed_1 = require("./embed");
|
|
26
26
|
const enums_1 = require("./enums");
|
|
@@ -163,7 +163,37 @@ class EmbeddingSearch {
|
|
|
163
163
|
return (0, pgvector_1.vectorSearch)(options);
|
|
164
164
|
});
|
|
165
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* 单条文本转成向量。
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```ts
|
|
171
|
+
* const vector = await EmbeddingSearch.embed('衣服质量怎么样');
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
static embed(text, dimensions) {
|
|
175
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
176
|
+
return (0, embed_1.embed)(text, dimensions);
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* 批量获取文本向量。
|
|
181
|
+
*
|
|
182
|
+
* 调用百炼 embedding 接口,一次最多 25 条文本。
|
|
183
|
+
* 返回向量的顺序与输入顺序一致。
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* const vectors = await EmbeddingSearch.batchEmbed([
|
|
188
|
+
* '衣服质量怎么样',
|
|
189
|
+
* '物流速度快吗',
|
|
190
|
+
* ]);
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
static batchEmbed(texts, dimensions) {
|
|
194
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
195
|
+
return (0, embed_1.embedBatch)(texts, dimensions);
|
|
196
|
+
});
|
|
197
|
+
}
|
|
166
198
|
}
|
|
167
199
|
exports.EmbeddingSearch = EmbeddingSearch;
|
|
168
|
-
var embed_2 = require("./embed");
|
|
169
|
-
Object.defineProperty(exports, "embed", { enumerable: true, get: function () { return embed_2.embed; } });
|
package/dist/index.d.ts
CHANGED
|
@@ -30,8 +30,16 @@ export { BailianProvider } from './predict';
|
|
|
30
30
|
export { MODEL_REGISTRY } from './llm_provider';
|
|
31
31
|
export type { Model } from './llm_provider';
|
|
32
32
|
export type { PredictConfig, PredictWithMessagesConfig } from './predict';
|
|
33
|
-
/**
|
|
34
|
-
|
|
33
|
+
/**
|
|
34
|
+
* 向量检索静态入口类。
|
|
35
|
+
*
|
|
36
|
+
* 提供 embedding 生成、批量 embedding 生成、pgvector 向量检索与 rerank 的完整链路:
|
|
37
|
+
* - `EmbeddingSearch.query()` — 文本 → embedding → pgvector 检索 → 可选 rerank
|
|
38
|
+
* - `EmbeddingSearch.vectorSearch()` — 已有向量 → pgvector 近邻检索
|
|
39
|
+
* - `EmbeddingSearch.embed()` — 单条文本转向量
|
|
40
|
+
* - `EmbeddingSearch.batchEmbed()` — 批量文本转向量(单次最多 25 条)
|
|
41
|
+
*/
|
|
42
|
+
export { EmbeddingSearch } from './embedding_search';
|
|
35
43
|
export type { EmbeddingSearchConfig, SearchResult } from './embedding_search';
|
|
36
44
|
/** Function Call Loop */
|
|
37
45
|
export * as FunctionCallLoop from './function_call_loop';
|
package/dist/index.js
CHANGED
|
@@ -53,7 +53,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
53
53
|
};
|
|
54
54
|
})();
|
|
55
55
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56
|
-
exports.FunctionCallLoop = exports.
|
|
56
|
+
exports.FunctionCallLoop = exports.EmbeddingSearch = exports.MODEL_REGISTRY = exports.BailianProvider = exports.Predictor = exports.LLM = void 0;
|
|
57
57
|
/** LLM 静态入口类,封装 Provider 连接、故障转移和返回解析 */
|
|
58
58
|
var predict_1 = require("./predict");
|
|
59
59
|
Object.defineProperty(exports, "LLM", { enumerable: true, get: function () { return predict_1.LLM; } });
|
|
@@ -66,9 +66,16 @@ Object.defineProperty(exports, "BailianProvider", { enumerable: true, get: funct
|
|
|
66
66
|
/** 模型注册表与枚举,定义模型与 Provider 的映射关系 */
|
|
67
67
|
var llm_provider_1 = require("./llm_provider");
|
|
68
68
|
Object.defineProperty(exports, "MODEL_REGISTRY", { enumerable: true, get: function () { return llm_provider_1.MODEL_REGISTRY; } });
|
|
69
|
-
/**
|
|
69
|
+
/**
|
|
70
|
+
* 向量检索静态入口类。
|
|
71
|
+
*
|
|
72
|
+
* 提供 embedding 生成、批量 embedding 生成、pgvector 向量检索与 rerank 的完整链路:
|
|
73
|
+
* - `EmbeddingSearch.query()` — 文本 → embedding → pgvector 检索 → 可选 rerank
|
|
74
|
+
* - `EmbeddingSearch.vectorSearch()` — 已有向量 → pgvector 近邻检索
|
|
75
|
+
* - `EmbeddingSearch.embed()` — 单条文本转向量
|
|
76
|
+
* - `EmbeddingSearch.batchEmbed()` — 批量文本转向量(单次最多 25 条)
|
|
77
|
+
*/
|
|
70
78
|
var embedding_search_1 = require("./embedding_search");
|
|
71
79
|
Object.defineProperty(exports, "EmbeddingSearch", { enumerable: true, get: function () { return embedding_search_1.EmbeddingSearch; } });
|
|
72
|
-
Object.defineProperty(exports, "embed", { enumerable: true, get: function () { return embedding_search_1.embed; } });
|
|
73
80
|
/** Function Call Loop */
|
|
74
81
|
exports.FunctionCallLoop = __importStar(require("./function_call_loop"));
|
|
@@ -48,7 +48,7 @@ class BailianProvider {
|
|
|
48
48
|
return BailianProvider.SUPPORTED_MODELS.has(model);
|
|
49
49
|
}
|
|
50
50
|
adaptRequest(body) {
|
|
51
|
-
var _a, _b, _c;
|
|
51
|
+
var _a, _b, _c, _d;
|
|
52
52
|
const caps = (_a = BailianProvider.MODEL_CAPABILITIES[body.model]) !== null && _a !== void 0 ? _a : { jsonMode: false, reasoningEffort: false };
|
|
53
53
|
if (body.reasoning_effort !== undefined && !caps.reasoningEffort) {
|
|
54
54
|
throw new Error(`[adapt] Model "${body.model}" does not support reasoning_effort`);
|
|
@@ -57,12 +57,21 @@ class BailianProvider {
|
|
|
57
57
|
throw new Error(`[adapt] Model "${body.model}" does not support response_format json_object`);
|
|
58
58
|
}
|
|
59
59
|
// 百炼平台:Qwen 系列通过 enable_thinking 实现 reasoning_effort
|
|
60
|
+
// Kimi(Moonshot)通过 extra_body.thinking.type 实现(默认开启)
|
|
60
61
|
if (body.reasoning_effort !== undefined) {
|
|
61
62
|
if (['qwen-plus', 'qwen-turbo', 'qwen3.7-max'].includes(body.model)) {
|
|
62
63
|
const { reasoning_effort } = body, rest = __rest(body, ["reasoning_effort"]);
|
|
63
64
|
return Object.assign(Object.assign({}, rest), { extra_body: Object.assign(Object.assign({}, ((_c = rest.extra_body) !== null && _c !== void 0 ? _c : {})), { enable_thinking: reasoning_effort !== 'low' }) });
|
|
64
65
|
}
|
|
65
|
-
|
|
66
|
+
if (body.model === 'kimi-k2.6') {
|
|
67
|
+
const { reasoning_effort } = body, rest = __rest(body, ["reasoning_effort"]);
|
|
68
|
+
// Kimi 默认开启思考;只有 low 显式禁用,medium/high 走默认(不传 thinking 字段)
|
|
69
|
+
if (reasoning_effort === 'low') {
|
|
70
|
+
return Object.assign(Object.assign({}, rest), { extra_body: Object.assign(Object.assign({}, ((_d = rest.extra_body) !== null && _d !== void 0 ? _d : {})), { thinking: { type: 'disabled' } }) });
|
|
71
|
+
}
|
|
72
|
+
return rest;
|
|
73
|
+
}
|
|
74
|
+
// deepseek-v4-pro / deepseek-v4-flash 原生支持 reasoning_effort,直接传递
|
|
66
75
|
}
|
|
67
76
|
return body;
|
|
68
77
|
}
|
|
@@ -198,6 +207,7 @@ class BailianProvider {
|
|
|
198
207
|
: undefined,
|
|
199
208
|
stream: request.stream,
|
|
200
209
|
stream_options: request.streamOptions,
|
|
210
|
+
reasoning_effort: request.reasoningEffort,
|
|
201
211
|
};
|
|
202
212
|
}
|
|
203
213
|
}
|
|
@@ -19,6 +19,8 @@ export interface LLMRequest {
|
|
|
19
19
|
};
|
|
20
20
|
readonly model?: string;
|
|
21
21
|
readonly responseFormat?: 'text' | 'json';
|
|
22
|
+
/** 推理深度。各 Provider 按自身能力映射到底层协议字段(如 enable_thinking / reasoning_effort) */
|
|
23
|
+
readonly reasoningEffort?: 'low' | 'medium' | 'high';
|
|
22
24
|
}
|
|
23
25
|
/**
|
|
24
26
|
* LLM 调用的 token 消耗统计。
|
package/dist/predict/predict.js
CHANGED