@keo-ai/axiom 0.1.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 ADDED
@@ -0,0 +1,187 @@
1
+ <div align="center">
2
+
3
+ # ⚡ AXIOM
4
+
5
+ > **The execution foundation for LLM agents.**
6
+
7
+
8
+ **Axiom 不是编排框架。它是大模型调用工具的「底盘」**
9
+
10
+
11
+ </div>
12
+
13
+ ---
14
+
15
+ ## 什么是 Axiom
16
+
17
+ Axiom 是 **keo** 的 LLM 底座库。它不碰业务编排(意图路由、节点流、客服话术),只解决一个问题:
18
+
19
+ > **当模型说「我要调用工具」时,确保它真的调了、真的拿到了结果、并且基于事实继续推理。**
20
+
21
+ 上层只管写业务节点(Conductor / 意图层 / 多模态预处理),Axiom 负责把 LLM → 工具 → 结果 → LLM 的循环跑稳。
22
+
23
+ ```
24
+ ┌────────────────────────────────────────────┐
25
+ │ 你的项目层(业务) │
26
+ │ 意图路由 · 节点编排 · 客服话术 · 业务Tool │
27
+ ├────────────────────────────────────────────┤
28
+ │ ⚡ AXIOM │
29
+ │ ┌─────────┐ ┌──────────┐ ┌─────────────┐ │
30
+ │ │ LLM调用 │ │ Harness │ │ 记忆系统 │ │
31
+ │ │ 故障转移 │ │ 状态机 │ │ · Faiss │ │
32
+ │ │ 流式输出 │ │ 副作用 │ │ · 槽位 │ │
33
+ │ └─────────┘ │ 传播 │ │ · 语义 │ │
34
+ │ │ 幻觉防控 │ └─────────────┘ │
35
+ │ └──────────┘ ┌─────────────┐ │
36
+ │ │ RAG基础 │ │
37
+ │ │ Embedding │ │
38
+ │ └─────────────┘ │
39
+ └────────────────────────────────────────────┘
40
+ ```
41
+
42
+ ## 架构边界
43
+
44
+ **Axiom 做:**
45
+ - ✅ LLM 统一调用 + Provider 故障转移
46
+ - ✅ Function Call Loop 的驱动、记录、校验、副作用传播
47
+ - ✅ 记忆系统的抽象与基础实现
48
+ - ✅ RAG 基础(Embedding / 向量检索)
49
+ - ✅ 基础配置中心
50
+
51
+ **Axiom 不做:**
52
+ - ❌ 意图识别与路由
53
+ - ❌ 业务节点编排(Conductor / DAG)
54
+ - ❌ 多模态预处理(语音/图片转文本)
55
+ - ❌ 消息队列与削峰
56
+ - ❌ 具体业务 Tool 的实现逻辑
57
+ - ❌ Provider 排序策略(成本/能力/速度)
58
+
59
+ > 上层写业务,Axiom 跑底盘。
60
+
61
+ ---
62
+
63
+ ## Predict 模块(LLM 调用)
64
+
65
+ Predict 是 Axiom 的 LLM 调用层。它封装了 Provider 连接、请求组装、故障转移和返回解析,让上层只需关心「用什么模型、传什么消息」。
66
+
67
+ ### 快速开始
68
+
69
+ 设置环境变量(百炼):
70
+
71
+ ```bash
72
+ export BAILIAN_API_KEY="your-api-key"
73
+ ```
74
+
75
+ 一行调用:
76
+
77
+ ```ts
78
+ import { LLM } from '@keo-ai/axiom';
79
+
80
+ const res = await LLM.predict({ model: 'qwen3.7-max', prompt: '你好' });
81
+ console.log(res.content);
82
+ ```
83
+
84
+ ### API 概览
85
+
86
+ | 方法 | 用途 | 返回类型 |
87
+ |---|---|---|
88
+ | `LLM.predict(config)` | 单轮快速调用,自动构建 user message | 依 `responseFormat` 而定(见下) |
89
+ | `LLM.predictWithMessages(messages, config)` | 传入完整消息列表,适用于多轮对话 | 同上 |
90
+ | `LLM.streamPredict(config)` | 流式调用,逐块返回内容 | `AsyncGenerator<StreamChunk>` |
91
+ | `LLM.streamPredictWithMessages(messages, config)` | 流式 + 自定义消息列表 | `AsyncGenerator<StreamChunk>` |
92
+
93
+ ### responseFormat 与返回类型
94
+
95
+ `predict` 和 `predictWithMessages` 的返回类型由 `responseFormat` 决定:
96
+
97
+ | `responseFormat` | 返回值 | 说明 |
98
+ |---|---|---|
99
+ | `'text'` | `string` | 直接返回模型输出的文本 |
100
+ | `'json'` | `any` | 自动 `JSON.parse` |
101
+ | 未设置 | `LLMResponse` | 完整响应(含 `content`、`usage`、`model`) |
102
+
103
+ ```ts
104
+ // text → string
105
+ const text = await LLM.predict({ model: 'qwen3.7-max', prompt: '讲个故事', responseFormat: 'text' });
106
+
107
+ // json → 自动解析为对象
108
+ const obj = await LLM.predict({
109
+ model: 'qwen3.7-max',
110
+ prompt: '生成一个 JSON',
111
+ responseFormat: 'json',
112
+ });
113
+ console.log(obj.name);
114
+ ```
115
+
116
+ ### Provider 配置
117
+
118
+ 设置环境变量即可,无需代码改动。
119
+
120
+ ```bash
121
+ BAILIAN_API_KEY # 必填
122
+ BAILIAN_BASE_URL # 可选,默认 https://dashscope.aliyuncs.com/compatible-mode/v1
123
+ BAILIAN_DEFAULT_MODEL # 可选,默认 qwen3.7-max
124
+ ```
125
+
126
+ ### 故障转移
127
+
128
+ Predictor 内部按模型查询 `MODEL_REGISTRY`,获取候选 Provider 队列,再通过 `provider.supports(model)` 做二次校验。当某个 Provider 失败或不支持该模型时,自动尝试下一个,直到成功或全部失败。
129
+
130
+ 全部失败时抛出汇总错误:`All providers failed: bailian: HTTP 500...; bailian: timeout...`
131
+
132
+ ### 流式调用
133
+
134
+ 流式版本返回 `AsyncGenerator<StreamChunk>`,迭代即可逐块消费:
135
+
136
+ ```ts
137
+ for await (const chunk of LLM.streamPredict({ model: 'qwen3.7-max', prompt: '讲个故事' })) {
138
+ if (chunk.type === 'content') {
139
+ process.stdout.write(chunk.delta);
140
+ }
141
+ }
142
+ ```
143
+
144
+ ### 模型列表
145
+
146
+ 当前支持的模型(通过 `Model` 类型枚举):
147
+
148
+ - `qwen3.7-max`
149
+ - `qwen-plus`
150
+ - `qwen-turbo`
151
+ - `qwq-plus`
152
+ - `deepseek-v4-pro`
153
+ - `deepseek-v4-flash`
154
+ - `kimi-k2.6`
155
+ - `qwen-vl-plus`
156
+
157
+ > 目前所有模型均路由到百炼 Provider。后续接入其他厂商时,通过 `MODEL_REGISTRY` 扩展映射即可。
158
+
159
+ ### 错误处理
160
+
161
+ Predict 模块遵循 Axiom 的统一错误策略:**直接抛异常,调用方 `try/catch`**。不使用 `Result<T, E>` 包装,不定义自定义错误类。
162
+
163
+ ```ts
164
+ try {
165
+ const res = await LLM.predict({ model: 'qwen3.7-max', prompt: 'hi' });
166
+ } catch (e) {
167
+ // e.message 包含 Provider 汇总错误信息
168
+ }
169
+ ```
170
+
171
+ ---
172
+
173
+ ## 设计理念
174
+
175
+ ```
176
+ ┌────────────────────────────────────────┐
177
+ │ Axiom 不纠正模型。 │
178
+ │ Axiom 保证模型永远不会基于幻觉推理。 │
179
+ └────────────────────────────────────────┘
180
+ ```
181
+
182
+ - **底座驱动循环** — Axiom 串起 LLM → 解析 → 校验 → 执行 → 记录的闭环
183
+ - **项目层填充内容** — 上层准备消息、工具、业务逻辑,Axiom 负责可靠执行
184
+ - **副作用即状态** — 工具调用改变外部世界,Harness 让这种改变在 Loop 间可见
185
+ - **单一事实来源** — Harness 的执行记录是 Function Call 的唯一权威来源
186
+
187
+ ---
@@ -0,0 +1,5 @@
1
+ export { LLM } from './predict';
2
+ export type { LLMRequest, LLMResponse, Message, ProviderConfig, StreamChunk, } from './predict';
3
+ export type { LLMProvider, PredictorOptions } from './predict';
4
+ export { Predictor, BailianProvider, MODEL_REGISTRY } from './predict';
5
+ export type { Model, PredictConfig, PredictWithMessagesConfig } from './predict';
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MODEL_REGISTRY = exports.BailianProvider = exports.Predictor = exports.LLM = void 0;
4
+ var predict_1 = require("./predict");
5
+ Object.defineProperty(exports, "LLM", { enumerable: true, get: function () { return predict_1.LLM; } });
6
+ var predict_2 = require("./predict");
7
+ Object.defineProperty(exports, "Predictor", { enumerable: true, get: function () { return predict_2.Predictor; } });
8
+ Object.defineProperty(exports, "BailianProvider", { enumerable: true, get: function () { return predict_2.BailianProvider; } });
9
+ Object.defineProperty(exports, "MODEL_REGISTRY", { enumerable: true, get: function () { return predict_2.MODEL_REGISTRY; } });
@@ -0,0 +1,37 @@
1
+ import type { Message } from './types';
2
+ import type { Model } from './models';
3
+ /**
4
+ * `predict()` 的配置参数。用于单轮快速调用场景,内部自动构建 user message。
5
+ */
6
+ export interface PredictConfig {
7
+ /** 模型枚举值,决定路由到哪个 Provider */
8
+ readonly model: Model;
9
+ /** 用户输入的 prompt */
10
+ readonly prompt: string;
11
+ /** 系统提示(可选) */
12
+ readonly systemPrompt?: string;
13
+ readonly temperature?: number;
14
+ readonly maxTokens?: number;
15
+ readonly topP?: number;
16
+ readonly reasoningEffort?: 'low' | 'medium' | 'high';
17
+ readonly responseFormat?: 'text' | 'json';
18
+ }
19
+ /**
20
+ * `predictWithMessages()` 的配置参数。不含 prompt,因为消息由调用方自行构建。
21
+ */
22
+ export interface PredictWithMessagesConfig {
23
+ readonly model: Model;
24
+ readonly systemPrompt?: string;
25
+ readonly temperature?: number;
26
+ readonly maxTokens?: number;
27
+ readonly topP?: number;
28
+ readonly reasoningEffort?: 'low' | 'medium' | 'high';
29
+ readonly responseFormat?: 'text' | 'json';
30
+ }
31
+ /**
32
+ * 将 system prompt 前置到消息列表中。
33
+ * @param config - 含可选 systemPrompt 字段的配置
34
+ * @param userMessages - 用户提供的消息列表
35
+ * @returns 带 system message 前缀的完整列表
36
+ */
37
+ export declare function buildMessages(config: PredictConfig | PredictWithMessagesConfig, userMessages: ReadonlyArray<Message>): Message[];
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildMessages = buildMessages;
4
+ /**
5
+ * 将 system prompt 前置到消息列表中。
6
+ * @param config - 含可选 systemPrompt 字段的配置
7
+ * @param userMessages - 用户提供的消息列表
8
+ * @returns 带 system message 前缀的完整列表
9
+ */
10
+ function buildMessages(config, userMessages) {
11
+ const messages = [];
12
+ if (config.systemPrompt) {
13
+ messages.push({ role: 'system', content: config.systemPrompt });
14
+ }
15
+ messages.push(...userMessages);
16
+ return messages;
17
+ }
@@ -0,0 +1,8 @@
1
+ export type { LLMRequest, LLMResponse, Message, ProviderConfig, StreamChunk, } from './types';
2
+ export type { LLMProvider, PredictorOptions } from './llm';
3
+ export { Predictor } from './llm';
4
+ export { BailianProvider } from './providers/bailian';
5
+ export type { Model } from './models';
6
+ export { MODEL_REGISTRY } from './models';
7
+ export type { PredictConfig, PredictWithMessagesConfig } from './config';
8
+ export { LLM } from './predict';
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LLM = exports.MODEL_REGISTRY = exports.BailianProvider = exports.Predictor = void 0;
4
+ var llm_1 = require("./llm");
5
+ Object.defineProperty(exports, "Predictor", { enumerable: true, get: function () { return llm_1.Predictor; } });
6
+ var bailian_1 = require("./providers/bailian");
7
+ Object.defineProperty(exports, "BailianProvider", { enumerable: true, get: function () { return bailian_1.BailianProvider; } });
8
+ var models_1 = require("./models");
9
+ Object.defineProperty(exports, "MODEL_REGISTRY", { enumerable: true, get: function () { return models_1.MODEL_REGISTRY; } });
10
+ var predict_1 = require("./predict");
11
+ Object.defineProperty(exports, "LLM", { enumerable: true, get: function () { return predict_1.LLM; } });
@@ -0,0 +1,72 @@
1
+ import type { LLMRequest, LLMResponse, ProviderConfig, StreamChunk } from './types';
2
+ import type { Model } from './models';
3
+ /**
4
+ * LLM Provider 抽象接口。每个 Provider 实现负责对接具体的模型服务
5
+ *(如百炼、OpenAI、Anthropic 等),处理 HTTP 请求、流式解析和错误转换。
6
+ */
7
+ export interface LLMProvider {
8
+ /** Provider 标识名,用于路由和故障转移日志 */
9
+ readonly name: string;
10
+ /** Provider 配置(API Key、Base URL、默认模型等) */
11
+ readonly config: ProviderConfig;
12
+ /**
13
+ * 校验当前 Provider 是否支持指定模型。
14
+ * 框架层在 MODEL_REGISTRY 候选过滤后,再调用此方法做二次确认。
15
+ * @param model - 模型标识名
16
+ * @returns true 表示支持,false 表示不支持(将自动轮询下一个候选)
17
+ */
18
+ supports(model: string): boolean;
19
+ /**
20
+ * 发送非流式请求,返回完整的模型响应。
21
+ * @param request - LLM 请求参数
22
+ * @returns 模型生成的完整响应
23
+ * @throws 网络异常、HTTP 错误、解析失败等均抛 {@link Error}
24
+ */
25
+ generate(request: LLMRequest): Promise<LLMResponse>;
26
+ /**
27
+ * 发送流式请求,逐块返回模型输出。
28
+ * @param request - LLM 请求参数
29
+ * @yields 内容片段或结束标记
30
+ * @throws 网络异常、HTTP 错误等均抛 {@link Error}
31
+ */
32
+ stream(request: LLMRequest): AsyncGenerator<StreamChunk, void, unknown>;
33
+ }
34
+ /** Predictor 构造选项 */
35
+ export interface PredictorOptions {
36
+ /** Provider 列表,按优先级排序 */
37
+ readonly providers: ReadonlyArray<LLMProvider>;
38
+ /** 单个 Provider 失败后的最大重试次数,默认 1 */
39
+ readonly maxRetries?: number;
40
+ /** 重试间隔(毫秒),默认 0 */
41
+ readonly retryDelayMs?: number;
42
+ }
43
+ /**
44
+ * 预测器核心类。负责按模型路由到对应 Provider,执行故障转移和重试。
45
+ * 对外透明:调用方只需指定模型,无需关心底层是哪个 Provider。
46
+ */
47
+ export declare class Predictor {
48
+ private readonly providers;
49
+ private readonly maxRetries;
50
+ private readonly retryDelayMs;
51
+ constructor(options: PredictorOptions);
52
+ /** 当前已注册的 Provider 数量 */
53
+ get providerCount(): number;
54
+ /**
55
+ * 非流式生成。按模型找到对应 Provider 队列,逐个尝试直到成功。
56
+ * @param model - 模型枚举值
57
+ * @param request - 标准化后的 LLM 请求
58
+ * @returns 模型响应
59
+ * @throws Error - 模型不存在、无可用 Provider、或所有 Provider 均失败时抛出
60
+ */
61
+ generateForModel(model: Model, request: LLMRequest): Promise<LLMResponse>;
62
+ /**
63
+ * 流式生成。按模型找到对应 Provider 队列,逐个尝试直到成功建立流。
64
+ * @param model - 模型枚举值
65
+ * @param request - 标准化后的 LLM 请求
66
+ * @yields 内容片段或结束标记
67
+ * @throws Error - 模型不存在、无可用 Provider、或所有 Provider 均失败时抛出
68
+ */
69
+ streamForModel(model: Model, request: LLMRequest): AsyncGenerator<StreamChunk, void, unknown>;
70
+ private buildProviderQueue;
71
+ private sleep;
72
+ }
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
12
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
13
+ var m = o[Symbol.asyncIterator], i;
14
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
15
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
16
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
17
+ };
18
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
19
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
20
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
21
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
22
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
23
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
24
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
25
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
26
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
27
+ function fulfill(value) { resume("next", value); }
28
+ function reject(value) { resume("throw", value); }
29
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
30
+ };
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.Predictor = void 0;
33
+ const models_1 = require("./models");
34
+ /**
35
+ * 预测器核心类。负责按模型路由到对应 Provider,执行故障转移和重试。
36
+ * 对外透明:调用方只需指定模型,无需关心底层是哪个 Provider。
37
+ */
38
+ class Predictor {
39
+ constructor(options) {
40
+ var _a, _b;
41
+ if (options.providers.length === 0) {
42
+ throw new Error('At least one provider is required');
43
+ }
44
+ this.providers = [...options.providers];
45
+ this.maxRetries = (_a = options.maxRetries) !== null && _a !== void 0 ? _a : 1;
46
+ this.retryDelayMs = (_b = options.retryDelayMs) !== null && _b !== void 0 ? _b : 0;
47
+ }
48
+ /** 当前已注册的 Provider 数量 */
49
+ get providerCount() {
50
+ return this.providers.length;
51
+ }
52
+ /**
53
+ * 非流式生成。按模型找到对应 Provider 队列,逐个尝试直到成功。
54
+ * @param model - 模型枚举值
55
+ * @param request - 标准化后的 LLM 请求
56
+ * @returns 模型响应
57
+ * @throws Error - 模型不存在、无可用 Provider、或所有 Provider 均失败时抛出
58
+ */
59
+ generateForModel(model, request) {
60
+ return __awaiter(this, void 0, void 0, function* () {
61
+ const candidates = models_1.MODEL_REGISTRY[model];
62
+ if (!candidates || candidates.length === 0) {
63
+ throw new Error(`Unknown model: ${model}`);
64
+ }
65
+ const providerQueue = this.buildProviderQueue(candidates);
66
+ if (providerQueue.length === 0) {
67
+ throw new Error(`No provider available for model: ${model}`);
68
+ }
69
+ const errors = [];
70
+ for (const { provider, modelConfig } of providerQueue) {
71
+ const modelRequest = Object.assign(Object.assign({}, request), { model: modelConfig.model });
72
+ for (let attempt = 0; attempt < this.maxRetries; attempt++) {
73
+ try {
74
+ return yield provider.generate(modelRequest);
75
+ }
76
+ catch (error) {
77
+ const err = error instanceof Error ? error : new Error(String(error));
78
+ errors.push({ provider: provider.name, error: err });
79
+ }
80
+ if (attempt < this.maxRetries - 1 && this.retryDelayMs > 0) {
81
+ yield this.sleep(this.retryDelayMs);
82
+ }
83
+ }
84
+ }
85
+ const summary = errors.map((e) => `${e.provider}: ${e.error.message}`).join('; ');
86
+ throw new Error(`All providers failed: ${summary}`);
87
+ });
88
+ }
89
+ /**
90
+ * 流式生成。按模型找到对应 Provider 队列,逐个尝试直到成功建立流。
91
+ * @param model - 模型枚举值
92
+ * @param request - 标准化后的 LLM 请求
93
+ * @yields 内容片段或结束标记
94
+ * @throws Error - 模型不存在、无可用 Provider、或所有 Provider 均失败时抛出
95
+ */
96
+ streamForModel(model, request) {
97
+ return __asyncGenerator(this, arguments, function* streamForModel_1() {
98
+ var _a, e_1, _b, _c;
99
+ const candidates = models_1.MODEL_REGISTRY[model];
100
+ if (!candidates || candidates.length === 0) {
101
+ throw new Error(`Unknown model: ${model}`);
102
+ }
103
+ const providerQueue = this.buildProviderQueue(candidates);
104
+ if (providerQueue.length === 0) {
105
+ throw new Error(`No provider available for model: ${model}`);
106
+ }
107
+ const errors = [];
108
+ for (const { provider, modelConfig } of providerQueue) {
109
+ const modelRequest = Object.assign(Object.assign({}, request), { model: modelConfig.model });
110
+ try {
111
+ try {
112
+ for (var _d = true, _e = (e_1 = void 0, __asyncValues(provider.stream(modelRequest))), _f; _f = yield __await(_e.next()), _a = _f.done, !_a; _d = true) {
113
+ _c = _f.value;
114
+ _d = false;
115
+ const chunk = _c;
116
+ yield yield __await(chunk);
117
+ }
118
+ }
119
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
120
+ finally {
121
+ try {
122
+ if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e));
123
+ }
124
+ finally { if (e_1) throw e_1.error; }
125
+ }
126
+ return yield __await(void 0);
127
+ }
128
+ catch (error) {
129
+ const err = error instanceof Error ? error : new Error(String(error));
130
+ errors.push({ provider: provider.name, error: err });
131
+ }
132
+ }
133
+ const summary = errors.map((e) => `${e.provider}: ${e.error.message}`).join('; ');
134
+ throw new Error(`All providers failed: ${summary}`);
135
+ });
136
+ }
137
+ buildProviderQueue(candidates) {
138
+ const queue = [];
139
+ const seen = new Set();
140
+ for (const provider of this.providers) {
141
+ for (const mc of candidates) {
142
+ if (provider.name === mc.provider && !seen.has(provider) && provider.supports(mc.model)) {
143
+ seen.add(provider);
144
+ queue.push({ provider, modelConfig: mc });
145
+ }
146
+ }
147
+ }
148
+ return queue;
149
+ }
150
+ sleep(ms) {
151
+ return new Promise((resolve) => setTimeout(resolve, ms));
152
+ }
153
+ }
154
+ exports.Predictor = Predictor;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 支持的模型枚举。项目层通过此枚举选择模型,Axiom 内部路由到对应 Provider。
3
+ */
4
+ export type Model = 'qwen3.7-max' | 'qwen-plus' | 'qwen-turbo' | 'qwq-plus' | 'deepseek-v4-pro' | 'deepseek-v4-flash' | 'kimi-k2.6' | 'qwen-vl-plus';
5
+ /** 模型到 Provider 的映射配置 */
6
+ export interface ModelConfig {
7
+ readonly model: string;
8
+ readonly provider: string;
9
+ }
10
+ /**
11
+ * 模型注册表。每个模型对应一个或多个 Provider 候选,按优先级排序。
12
+ * 当首选 Provider 失败时,Predictor 按此表顺序尝试下一个。
13
+ */
14
+ export declare const MODEL_REGISTRY: Readonly<Record<Model, ReadonlyArray<ModelConfig>>>;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MODEL_REGISTRY = void 0;
4
+ /**
5
+ * 模型注册表。每个模型对应一个或多个 Provider 候选,按优先级排序。
6
+ * 当首选 Provider 失败时,Predictor 按此表顺序尝试下一个。
7
+ */
8
+ exports.MODEL_REGISTRY = {
9
+ 'qwen3.7-max': [{ model: 'qwen3.7-max', provider: 'bailian' }],
10
+ 'qwen-plus': [{ model: 'qwen-plus', provider: 'bailian' }],
11
+ 'qwen-turbo': [{ model: 'qwen-turbo', provider: 'bailian' }],
12
+ 'qwq-plus': [{ model: 'qwq-plus', provider: 'bailian' }],
13
+ 'deepseek-v4-pro': [{ model: 'deepseek-v4-pro', provider: 'bailian' }],
14
+ 'deepseek-v4-flash': [{ model: 'deepseek-v4-flash', provider: 'bailian' }],
15
+ 'kimi-k2.6': [{ model: 'kimi-k2.6', provider: 'bailian' }],
16
+ 'qwen-vl-plus': [{ model: 'qwen-vl-plus', provider: 'bailian' }],
17
+ };
@@ -0,0 +1,82 @@
1
+ import type { Message, LLMResponse, StreamChunk } from './types';
2
+ import type { PredictConfig, PredictWithMessagesConfig } from './config';
3
+ /**
4
+ * LLM 静态类。封装 Provider 连接、请求组装、故障转移和返回解析。
5
+ * 上层只需关心「用什么模型、传什么消息」,通过静态方法直接调用。
6
+ *
7
+ * @example
8
+ * ```ts
9
+ * import { LLM } from 'axiom';
10
+ *
11
+ * const res = await LLM.predict({ model: 'qwen-max', prompt: '你好' });
12
+ * console.log(res.content);
13
+ * ```
14
+ */
15
+ export declare class LLM {
16
+ private static globalPredictor;
17
+ private static getPredictor;
18
+ /**
19
+ * 快速调用 LLM,传入 prompt 和配置即可。
20
+ * 内部自动构造单条 user message,支持可选的 system prompt。
21
+ *
22
+ * 根据 `responseFormat` 返回不同类型:
23
+ * - `'text'` → `string`
24
+ * - `'json'` → 解析后的对象(`any`)
25
+ * - 未设置 → `LLMResponse`
26
+ *
27
+ * @param config - 预测配置(模型、prompt、温度等)
28
+ * @returns 模型生成的完整响应
29
+ * @throws Error - Provider 未配置、模型不存在、或所有 Provider 均失败时抛出
30
+ */
31
+ static predict(config: PredictConfig & {
32
+ responseFormat: 'text';
33
+ }): Promise<string>;
34
+ static predict(config: PredictConfig & {
35
+ responseFormat: 'json';
36
+ }): Promise<any>;
37
+ static predict(config: PredictConfig): Promise<LLMResponse>;
38
+ /**
39
+ * 使用自定义消息列表调用 LLM。适用于多轮对话等需要精细控制 message 结构的场景。
40
+ *
41
+ * 根据 `responseFormat` 返回不同类型:
42
+ * - `'text'` → `string`
43
+ * - `'json'` → 解析后的对象(可用泛型指定类型)
44
+ * - 未设置 → `LLMResponse`
45
+ *
46
+ * @param messages - 消息列表(user/assistant 角色)
47
+ * @param config - 预测配置(不含 prompt,因为由 messages 提供)
48
+ * @returns 模型生成的完整响应
49
+ * @throws Error - Provider 未配置、模型不存在、或所有 Provider 均失败时抛出
50
+ */
51
+ static predictWithMessages(messages: ReadonlyArray<Message>, config: PredictWithMessagesConfig & {
52
+ responseFormat: 'text';
53
+ }): Promise<string>;
54
+ static predictWithMessages(messages: ReadonlyArray<Message>, config: PredictWithMessagesConfig & {
55
+ responseFormat: 'json';
56
+ }): Promise<any>;
57
+ static predictWithMessages(messages: ReadonlyArray<Message>, config: PredictWithMessagesConfig): Promise<LLMResponse>;
58
+ /**
59
+ * 流式调用 LLM,逐块返回模型输出。
60
+ *
61
+ * @param config - 预测配置
62
+ * @yields 内容片段(`content`)或结束标记(`finish`)
63
+ * @throws Error - Provider 未配置、模型不存在、或所有 Provider 均失败时抛出
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * for await (const chunk of LLM.streamPredict({ model: 'qwen-max', prompt: '讲个故事' })) {
68
+ * if (chunk.type === 'content') process.stdout.write(chunk.delta);
69
+ * }
70
+ * ```
71
+ */
72
+ static streamPredict(config: PredictConfig): AsyncGenerator<StreamChunk, void, unknown>;
73
+ /**
74
+ * 使用自定义消息列表进行流式调用。
75
+ *
76
+ * @param messages - 消息列表
77
+ * @param config - 预测配置
78
+ * @yields 内容片段或结束标记
79
+ * @throws Error - Provider 未配置、模型不存在、或所有 Provider 均失败时抛出
80
+ */
81
+ static streamPredictWithMessages(messages: ReadonlyArray<Message>, config: PredictWithMessagesConfig): AsyncGenerator<StreamChunk, void, unknown>;
82
+ }
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
12
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
13
+ var m = o[Symbol.asyncIterator], i;
14
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
15
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
16
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
17
+ };
18
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
19
+ var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
20
+ var i, p;
21
+ return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
22
+ function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }
23
+ };
24
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
25
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
26
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
27
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
28
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
29
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
30
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
31
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
32
+ function fulfill(value) { resume("next", value); }
33
+ function reject(value) { resume("throw", value); }
34
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
35
+ };
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.LLM = void 0;
38
+ const llm_1 = require("./llm");
39
+ const config_1 = require("./config");
40
+ const bailian_1 = require("./providers/bailian");
41
+ const DEFAULT_BAILIAN_BASE_URL = 'https://dashscope.aliyuncs.com/compatible-mode/v1';
42
+ const DEFAULT_BAILIAN_MODEL = 'qwen-max';
43
+ function createBailianProvider() {
44
+ var _a, _b;
45
+ if (!process.env.BAILIAN_API_KEY)
46
+ return null;
47
+ return new bailian_1.BailianProvider({
48
+ name: 'bailian',
49
+ apiKey: process.env.BAILIAN_API_KEY,
50
+ baseUrl: (_a = process.env.BAILIAN_BASE_URL) !== null && _a !== void 0 ? _a : DEFAULT_BAILIAN_BASE_URL,
51
+ defaultModel: (_b = process.env.BAILIAN_DEFAULT_MODEL) !== null && _b !== void 0 ? _b : DEFAULT_BAILIAN_MODEL,
52
+ });
53
+ }
54
+ function createDefaultProviders() {
55
+ return [
56
+ createBailianProvider(),
57
+ // createOpenAIProvider(),
58
+ // createAnthropicProvider(),
59
+ ].filter((p) => p !== null);
60
+ }
61
+ function toLLMRequest(config, messages) {
62
+ return {
63
+ messages,
64
+ temperature: config.temperature,
65
+ maxTokens: config.maxTokens,
66
+ topP: config.topP,
67
+ responseFormat: config.responseFormat,
68
+ };
69
+ }
70
+ function unwrapResponse(response, responseFormat) {
71
+ var _a;
72
+ if (responseFormat === 'text') {
73
+ return (_a = response.content) !== null && _a !== void 0 ? _a : '';
74
+ }
75
+ if (responseFormat === 'json') {
76
+ if (!response.content) {
77
+ throw new Error('Empty response content when responseFormat is json');
78
+ }
79
+ return JSON.parse(response.content);
80
+ }
81
+ return response;
82
+ }
83
+ /**
84
+ * LLM 静态类。封装 Provider 连接、请求组装、故障转移和返回解析。
85
+ * 上层只需关心「用什么模型、传什么消息」,通过静态方法直接调用。
86
+ *
87
+ * @example
88
+ * ```ts
89
+ * import { LLM } from 'axiom';
90
+ *
91
+ * const res = await LLM.predict({ model: 'qwen-max', prompt: '你好' });
92
+ * console.log(res.content);
93
+ * ```
94
+ */
95
+ class LLM {
96
+ static getPredictor() {
97
+ if (!LLM.globalPredictor) {
98
+ LLM.globalPredictor = new llm_1.Predictor({ providers: createDefaultProviders() });
99
+ }
100
+ if (LLM.globalPredictor.providerCount === 0) {
101
+ throw new Error('No LLM provider configured. Set BAILIAN_API_KEY environment variable.');
102
+ }
103
+ return LLM.globalPredictor;
104
+ }
105
+ static predict(config) {
106
+ return __awaiter(this, void 0, void 0, function* () {
107
+ const predictor = LLM.getPredictor();
108
+ const messages = (0, config_1.buildMessages)(config, [{ role: 'user', content: config.prompt }]);
109
+ const request = toLLMRequest(config, messages);
110
+ const response = yield predictor.generateForModel(config.model, request);
111
+ return unwrapResponse(response, config.responseFormat);
112
+ });
113
+ }
114
+ static predictWithMessages(messages, config) {
115
+ return __awaiter(this, void 0, void 0, function* () {
116
+ const predictor = LLM.getPredictor();
117
+ const builtMessages = (0, config_1.buildMessages)(config, messages);
118
+ const request = toLLMRequest(config, builtMessages);
119
+ const response = yield predictor.generateForModel(config.model, request);
120
+ return unwrapResponse(response, config.responseFormat);
121
+ });
122
+ }
123
+ /**
124
+ * 流式调用 LLM,逐块返回模型输出。
125
+ *
126
+ * @param config - 预测配置
127
+ * @yields 内容片段(`content`)或结束标记(`finish`)
128
+ * @throws Error - Provider 未配置、模型不存在、或所有 Provider 均失败时抛出
129
+ *
130
+ * @example
131
+ * ```ts
132
+ * for await (const chunk of LLM.streamPredict({ model: 'qwen-max', prompt: '讲个故事' })) {
133
+ * if (chunk.type === 'content') process.stdout.write(chunk.delta);
134
+ * }
135
+ * ```
136
+ */
137
+ static streamPredict(config) {
138
+ return __asyncGenerator(this, arguments, function* streamPredict_1() {
139
+ const predictor = LLM.getPredictor();
140
+ const messages = (0, config_1.buildMessages)(config, [{ role: 'user', content: config.prompt }]);
141
+ const request = toLLMRequest(config, messages);
142
+ yield __await(yield* __asyncDelegator(__asyncValues(predictor.streamForModel(config.model, request))));
143
+ });
144
+ }
145
+ /**
146
+ * 使用自定义消息列表进行流式调用。
147
+ *
148
+ * @param messages - 消息列表
149
+ * @param config - 预测配置
150
+ * @yields 内容片段或结束标记
151
+ * @throws Error - Provider 未配置、模型不存在、或所有 Provider 均失败时抛出
152
+ */
153
+ static streamPredictWithMessages(messages, config) {
154
+ return __asyncGenerator(this, arguments, function* streamPredictWithMessages_1() {
155
+ const predictor = LLM.getPredictor();
156
+ const builtMessages = (0, config_1.buildMessages)(config, messages);
157
+ const request = toLLMRequest(config, builtMessages);
158
+ yield __await(yield* __asyncDelegator(__asyncValues(predictor.streamForModel(config.model, request))));
159
+ });
160
+ }
161
+ }
162
+ exports.LLM = LLM;
163
+ LLM.globalPredictor = null;
@@ -0,0 +1,27 @@
1
+ import type { LLMProvider } from '../llm';
2
+ import type { LLMRequest, LLMResponse, ProviderConfig, StreamChunk } from '../types';
3
+ /**
4
+ * 阿里云百炼(兼容 OpenAI 协议)Provider 实现。
5
+ * 支持非流式调用和流式 SSE 输出。
6
+ */
7
+ export declare class BailianProvider implements LLMProvider {
8
+ readonly config: ProviderConfig;
9
+ readonly name = "bailian";
10
+ constructor(config: ProviderConfig);
11
+ supports(model: string): boolean;
12
+ /**
13
+ * 发送非流式 chat completion 请求到百炼服务。
14
+ * @param request - 标准化 LLM 请求
15
+ * @returns 解析后的模型响应(含 content、usage、model)
16
+ * @throws Error - 网络异常时抛 `[bailian] ...`;HTTP 非 2xx 时抛 `[bailian] HTTP {status}: ...`
17
+ */
18
+ generate(request: LLMRequest): Promise<LLMResponse>;
19
+ /**
20
+ * 发送流式 chat completion 请求,解析 SSE 响应逐块返回。
21
+ * @param request - 标准化 LLM 请求
22
+ * @yields 内容片段(`content`)或结束标记(`finish`)
23
+ * @throws Error - 网络异常或 HTTP 错误时抛出
24
+ */
25
+ stream(request: LLMRequest): AsyncGenerator<StreamChunk, void, unknown>;
26
+ private buildRequestBody;
27
+ }
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
12
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
13
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
14
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
15
+ return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
16
+ function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
17
+ function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
18
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
19
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
20
+ function fulfill(value) { resume("next", value); }
21
+ function reject(value) { resume("throw", value); }
22
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.BailianProvider = void 0;
26
+ const models_1 = require("../models");
27
+ /**
28
+ * 阿里云百炼(兼容 OpenAI 协议)Provider 实现。
29
+ * 支持非流式调用和流式 SSE 输出。
30
+ */
31
+ class BailianProvider {
32
+ constructor(config) {
33
+ this.config = config;
34
+ this.name = 'bailian';
35
+ }
36
+ supports(model) {
37
+ return Object.entries(models_1.MODEL_REGISTRY).some(([m, configs]) => m === model && configs.some((c) => c.provider === this.name));
38
+ }
39
+ /**
40
+ * 发送非流式 chat completion 请求到百炼服务。
41
+ * @param request - 标准化 LLM 请求
42
+ * @returns 解析后的模型响应(含 content、usage、model)
43
+ * @throws Error - 网络异常时抛 `[bailian] ...`;HTTP 非 2xx 时抛 `[bailian] HTTP {status}: ...`
44
+ */
45
+ generate(request) {
46
+ return __awaiter(this, void 0, void 0, function* () {
47
+ const url = `${this.config.baseUrl}/chat/completions`;
48
+ const body = this.buildRequestBody(request);
49
+ let response;
50
+ try {
51
+ response = yield fetch(url, {
52
+ method: 'POST',
53
+ headers: {
54
+ 'Content-Type': 'application/json',
55
+ Authorization: `Bearer ${this.config.apiKey}`,
56
+ },
57
+ body: JSON.stringify(Object.assign(Object.assign({}, body), { stream: false })),
58
+ });
59
+ }
60
+ catch (cause) {
61
+ throw new Error(`[${this.name}] ${cause instanceof Error ? cause.message : String(cause)}`);
62
+ }
63
+ if (!response.ok) {
64
+ const text = yield response.text();
65
+ throw new Error(`[${this.name}] HTTP ${response.status}: ${text}`);
66
+ }
67
+ const data = (yield response.json());
68
+ const choice = data.choices[0];
69
+ if (!choice) {
70
+ throw new Error(`[${this.name}] No choice in response`);
71
+ }
72
+ return {
73
+ content: choice.message.content,
74
+ usage: data.usage
75
+ ? {
76
+ promptTokens: data.usage.prompt_tokens,
77
+ completionTokens: data.usage.completion_tokens,
78
+ totalTokens: data.usage.total_tokens,
79
+ }
80
+ : undefined,
81
+ model: data.model,
82
+ };
83
+ });
84
+ }
85
+ /**
86
+ * 发送流式 chat completion 请求,解析 SSE 响应逐块返回。
87
+ * @param request - 标准化 LLM 请求
88
+ * @yields 内容片段(`content`)或结束标记(`finish`)
89
+ * @throws Error - 网络异常或 HTTP 错误时抛出
90
+ */
91
+ stream(request) {
92
+ return __asyncGenerator(this, arguments, function* stream_1() {
93
+ var _a, _b;
94
+ const url = `${this.config.baseUrl}/chat/completions`;
95
+ const body = this.buildRequestBody(request);
96
+ let response;
97
+ try {
98
+ response = yield __await(fetch(url, {
99
+ method: 'POST',
100
+ headers: {
101
+ 'Content-Type': 'application/json',
102
+ Authorization: `Bearer ${this.config.apiKey}`,
103
+ },
104
+ body: JSON.stringify(Object.assign(Object.assign({}, body), { stream: true })),
105
+ }));
106
+ }
107
+ catch (cause) {
108
+ throw new Error(`[${this.name}] ${cause instanceof Error ? cause.message : String(cause)}`);
109
+ }
110
+ if (!response.ok) {
111
+ const text = yield __await(response.text());
112
+ throw new Error(`[${this.name}] HTTP ${response.status}: ${text}`);
113
+ }
114
+ if (!response.body) {
115
+ throw new Error(`[${this.name}] Response body is null`);
116
+ }
117
+ const reader = response.body.getReader();
118
+ const decoder = new TextDecoder();
119
+ let buffer = '';
120
+ try {
121
+ while (true) {
122
+ const { done, value } = yield __await(reader.read());
123
+ if (done)
124
+ break;
125
+ buffer += decoder.decode(value, { stream: true });
126
+ const lines = buffer.split('\n');
127
+ buffer = (_a = lines.pop()) !== null && _a !== void 0 ? _a : '';
128
+ for (const line of lines) {
129
+ const trimmed = line.trim();
130
+ if (!trimmed || !trimmed.startsWith('data: '))
131
+ continue;
132
+ const data = trimmed.slice(6);
133
+ if (data === '[DONE]')
134
+ continue;
135
+ let parsed;
136
+ try {
137
+ parsed = JSON.parse(data);
138
+ }
139
+ catch (_c) {
140
+ continue;
141
+ }
142
+ const choice = (_b = parsed.choices) === null || _b === void 0 ? void 0 : _b[0];
143
+ if (!choice)
144
+ continue;
145
+ const delta = choice.delta;
146
+ if (delta.content) {
147
+ yield yield __await({ type: 'content', delta: delta.content });
148
+ }
149
+ if (choice.finish_reason && parsed.usage) {
150
+ yield yield __await({
151
+ type: 'finish',
152
+ usage: {
153
+ promptTokens: parsed.usage.prompt_tokens,
154
+ completionTokens: parsed.usage.completion_tokens,
155
+ totalTokens: parsed.usage.total_tokens,
156
+ },
157
+ });
158
+ }
159
+ }
160
+ }
161
+ yield yield __await({ type: 'finish' });
162
+ }
163
+ finally {
164
+ reader.releaseLock();
165
+ }
166
+ });
167
+ }
168
+ buildRequestBody(request) {
169
+ var _a;
170
+ return {
171
+ model: (_a = request.model) !== null && _a !== void 0 ? _a : this.config.defaultModel,
172
+ messages: request.messages.map((m) => ({
173
+ role: m.role,
174
+ content: m.content,
175
+ })),
176
+ temperature: request.temperature,
177
+ max_tokens: request.maxTokens,
178
+ top_p: request.topP,
179
+ response_format: request.responseFormat
180
+ ? { type: request.responseFormat === 'json' ? 'json_object' : 'text' }
181
+ : undefined,
182
+ };
183
+ }
184
+ }
185
+ exports.BailianProvider = BailianProvider;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * LLM 对话消息。支持 system、user、assistant 三种角色。
3
+ */
4
+ export interface Message {
5
+ readonly role: 'system' | 'user' | 'assistant';
6
+ readonly content: string;
7
+ }
8
+ /**
9
+ * 标准化 LLM 请求参数。各 Provider 据此构建自身的协议请求。
10
+ */
11
+ export interface LLMRequest {
12
+ readonly messages: ReadonlyArray<Message>;
13
+ readonly temperature?: number;
14
+ readonly maxTokens?: number;
15
+ readonly topP?: number;
16
+ readonly stream?: boolean;
17
+ readonly model?: string;
18
+ readonly responseFormat?: 'text' | 'json';
19
+ }
20
+ /**
21
+ * 标准化 LLM 响应。各 Provider 将原始响应解析为此格式后返回。
22
+ */
23
+ export interface LLMResponse {
24
+ readonly content: string | null;
25
+ readonly usage?: {
26
+ readonly promptTokens: number;
27
+ readonly completionTokens: number;
28
+ readonly totalTokens: number;
29
+ };
30
+ readonly model: string;
31
+ }
32
+ /**
33
+ * 流式输出片段。迭代器每次 yield 一个 chunk。
34
+ */
35
+ export type StreamChunk = {
36
+ readonly type: 'content';
37
+ readonly delta: string;
38
+ } | {
39
+ readonly type: 'finish';
40
+ readonly usage?: LLMResponse['usage'];
41
+ };
42
+ /**
43
+ * Provider 配置。每个 Provider 实例需要一组连接参数。
44
+ */
45
+ export interface ProviderConfig {
46
+ readonly name: string;
47
+ readonly apiKey: string;
48
+ readonly baseUrl: string;
49
+ readonly defaultModel: string;
50
+ readonly timeoutMs?: number;
51
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@keo-ai/axiom",
3
+ "version": "0.1.0",
4
+ "description": "基于 LLM 的预测与推理库,支持多 Provider 切换",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "license": "MIT",
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "test": "vitest run"
14
+ },
15
+ "dependencies": {
16
+ "dotenv": "^17.4.2"
17
+ },
18
+ "devDependencies": {
19
+ "@types/node": "^25.9.1",
20
+ "typescript": "^5.5.3",
21
+ "vitest": "^4.1.7"
22
+ }
23
+ }