plugin-ai-api 1.1.0 → 1.1.1
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/client/97.1bc5103fd9d995a8.js +10 -0
- package/dist/client/index.js +1 -1
- package/dist/client-v2/97.96da323832251796.js +10 -0
- package/dist/client-v2/index.js +1 -1
- package/dist/externalVersion.js +8 -8
- package/dist/locale/en-US.json +139 -138
- package/dist/locale/vi-VN.json +139 -138
- package/dist/locale/zh-CN.json +139 -138
- package/dist/server/billing.js +17 -9
- package/dist/server/collections/ai-api-model-prices.js +8 -0
- package/dist/server/collections/ai-api-usage-records.js +1 -0
- package/dist/server/migrations/20260827000000-add-cache-input-price.js +66 -0
- package/dist/server/routes/auth.js +16 -0
- package/dist/server/routes/embeddings.js +11 -1
- package/dist/server/usage.js +1 -0
- package/dist/server/utils/direct-llm-context.js +9 -8
- package/dist/server/validation.js +1 -0
- package/package.json +1 -1
- package/src/client/index.tsx +10 -10
- package/src/client/models/index.ts +12 -12
- package/src/client-v2/pages/ModelPricingPage.tsx +15 -0
- package/src/index.ts +11 -11
- package/src/locale/en-US.json +139 -138
- package/src/locale/vi-VN.json +139 -138
- package/src/locale/zh-CN.json +139 -138
- package/src/server/__tests__/billing-quota.test.ts +8 -2
- package/src/server/__tests__/billing.test.ts +13 -0
- package/src/server/__tests__/usage.test.ts +1 -0
- package/src/server/billing.ts +29 -6
- package/src/server/collections/ai-api-model-prices.ts +8 -0
- package/src/server/collections/ai-api-usage-records.ts +1 -0
- package/src/server/migrations/20260827000000-add-cache-input-price.ts +49 -0
- package/src/server/routes/auth.ts +21 -1
- package/src/server/routes/embeddings.ts +17 -3
- package/src/server/usage.ts +1 -0
- package/src/server/utils/direct-llm-context.ts +21 -11
- package/src/server/validation.ts +1 -0
- package/dist/client/97.9b6b2d2b01a4c060.js +0 -10
- package/dist/client-v2/97.36a42eff36bb3d8a.js +0 -10
package/dist/server/billing.js
CHANGED
|
@@ -86,9 +86,15 @@ function formatUnits(value, scale) {
|
|
|
86
86
|
function divideRounded(value, divisor) {
|
|
87
87
|
return (value + divisor / 2n) / divisor;
|
|
88
88
|
}
|
|
89
|
-
function calculateCostUnits(inputTokens, outputTokens, price) {
|
|
89
|
+
function calculateCostUnits(inputTokens, outputTokens, promptCacheTokens, price) {
|
|
90
|
+
const cachedInputTokens = Math.min(Math.max(promptCacheTokens, 0), inputTokens);
|
|
91
|
+
const uncachedInputTokens = inputTokens - cachedInputTokens;
|
|
90
92
|
const input = divideRounded(
|
|
91
|
-
BigInt(
|
|
93
|
+
BigInt(uncachedInputTokens) * decimalUnits(price.inputPricePerMillionTokens, PRICE_SCALE),
|
|
94
|
+
PRICE_TO_COST_DIVISOR
|
|
95
|
+
);
|
|
96
|
+
const cacheInput = divideRounded(
|
|
97
|
+
BigInt(cachedInputTokens) * decimalUnits(price.cacheInputPricePerMillionTokens, PRICE_SCALE),
|
|
92
98
|
PRICE_TO_COST_DIVISOR
|
|
93
99
|
);
|
|
94
100
|
const output = divideRounded(
|
|
@@ -96,10 +102,10 @@ function calculateCostUnits(inputTokens, outputTokens, price) {
|
|
|
96
102
|
PRICE_TO_COST_DIVISOR
|
|
97
103
|
);
|
|
98
104
|
const fixed = divideRounded(decimalUnits(price.fixedCostPerRequest, PRICE_SCALE), 100n);
|
|
99
|
-
return input + output + fixed;
|
|
105
|
+
return input + cacheInput + output + fixed;
|
|
100
106
|
}
|
|
101
|
-
function calculateLlmCost(inputTokens, outputTokens, price) {
|
|
102
|
-
return formatUnits(calculateCostUnits(inputTokens, outputTokens, price), COST_SCALE);
|
|
107
|
+
function calculateLlmCost(inputTokens, outputTokens, price, promptCacheTokens = 0) {
|
|
108
|
+
return formatUnits(calculateCostUnits(inputTokens, outputTokens, promptCacheTokens, price), COST_SCALE);
|
|
103
109
|
}
|
|
104
110
|
function normalizePositiveInteger(value, fallback) {
|
|
105
111
|
const parsed = Number(value);
|
|
@@ -145,6 +151,7 @@ async function findPrice(ctx, service, modelId) {
|
|
|
145
151
|
id: valueOf(price, "id"),
|
|
146
152
|
currency: valueOf(price, "currency"),
|
|
147
153
|
inputPricePerMillionTokens: decimalString(valueOf(price, "inputPricePerMillionTokens"), PRICE_SCALE),
|
|
154
|
+
cacheInputPricePerMillionTokens: decimalString(valueOf(price, "cacheInputPricePerMillionTokens"), PRICE_SCALE),
|
|
148
155
|
outputPricePerMillionTokens: decimalString(valueOf(price, "outputPricePerMillionTokens"), PRICE_SCALE),
|
|
149
156
|
fixedCostPerRequest: decimalString(valueOf(price, "fixedCostPerRequest"), PRICE_SCALE)
|
|
150
157
|
};
|
|
@@ -252,7 +259,7 @@ function usageNumbers(usage) {
|
|
|
252
259
|
};
|
|
253
260
|
}
|
|
254
261
|
async function finalizeLlmBilling(ctx, providerUsage, succeeded) {
|
|
255
|
-
var _a, _b, _c, _d, _e, _f;
|
|
262
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
256
263
|
const billing = stateOf(ctx).aiApiLlmBilling;
|
|
257
264
|
if (!billing) return {};
|
|
258
265
|
let numbers = usageNumbers(providerUsage);
|
|
@@ -269,7 +276,7 @@ async function finalizeLlmBilling(ctx, providerUsage, succeeded) {
|
|
|
269
276
|
} else {
|
|
270
277
|
costStatus = billing.price ? "usage_unavailable" : "unpriced";
|
|
271
278
|
}
|
|
272
|
-
const cost = numbers && billing.price ? calculateLlmCost(numbers.input, numbers.output, billing.price) : void 0;
|
|
279
|
+
const cost = numbers && billing.price ? calculateLlmCost(numbers.input, numbers.output, billing.price, (providerUsage == null ? void 0 : providerUsage.prompt_cache_tokens) ?? 0) : void 0;
|
|
273
280
|
const reservation = billing.reservation;
|
|
274
281
|
if (reservation) {
|
|
275
282
|
const Bucket = ctx.db.getModel("aiApiGroupQuotaBuckets");
|
|
@@ -315,8 +322,9 @@ async function finalizeLlmBilling(ctx, providerUsage, succeeded) {
|
|
|
315
322
|
groupId: reservation == null ? void 0 : reservation.groupId,
|
|
316
323
|
quotaMode: reservation == null ? void 0 : reservation.quotaMode,
|
|
317
324
|
inputPricePerMillionTokens: (_d = billing.price) == null ? void 0 : _d.inputPricePerMillionTokens,
|
|
318
|
-
|
|
319
|
-
|
|
325
|
+
cacheInputPricePerMillionTokens: (_e = billing.price) == null ? void 0 : _e.cacheInputPricePerMillionTokens,
|
|
326
|
+
outputPricePerMillionTokens: (_f = billing.price) == null ? void 0 : _f.outputPricePerMillionTokens,
|
|
327
|
+
fixedCostPerRequest: (_g = billing.price) == null ? void 0 : _g.fixedCostPerRequest
|
|
320
328
|
};
|
|
321
329
|
}
|
|
322
330
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -39,6 +39,14 @@ var ai_api_model_prices_default = (0, import_database.defineCollection)({
|
|
|
39
39
|
{ name: "model", type: "string", allowNull: false, index: true },
|
|
40
40
|
{ name: "currency", type: "string", allowNull: false, defaultValue: "USD" },
|
|
41
41
|
{ name: "inputPricePerMillionTokens", type: "decimal", precision: 20, scale: 10, allowNull: false },
|
|
42
|
+
{
|
|
43
|
+
name: "cacheInputPricePerMillionTokens",
|
|
44
|
+
type: "decimal",
|
|
45
|
+
precision: 20,
|
|
46
|
+
scale: 10,
|
|
47
|
+
allowNull: false,
|
|
48
|
+
defaultValue: 0
|
|
49
|
+
},
|
|
42
50
|
{ name: "outputPricePerMillionTokens", type: "decimal", precision: 20, scale: 10, allowNull: false },
|
|
43
51
|
{ name: "fixedCostPerRequest", type: "decimal", precision: 20, scale: 10, allowNull: false, defaultValue: 0 },
|
|
44
52
|
{ name: "effectiveFrom", type: "datetimeTz", allowNull: false, index: true },
|
|
@@ -70,6 +70,7 @@ var ai_api_usage_records_default = (0, import_database.defineCollection)({
|
|
|
70
70
|
{ name: "quotaPolicyId", type: "bigInt", allowNull: true, index: true },
|
|
71
71
|
{ name: "groupId", type: "bigInt", allowNull: true, index: true },
|
|
72
72
|
{ name: "inputPricePerMillionTokens", type: "decimal", allowNull: true, precision: 20, scale: 10 },
|
|
73
|
+
{ name: "cacheInputPricePerMillionTokens", type: "decimal", allowNull: true, precision: 20, scale: 10 },
|
|
73
74
|
{ name: "outputPricePerMillionTokens", type: "decimal", allowNull: true, precision: 20, scale: 10 },
|
|
74
75
|
{ name: "fixedCostPerRequest", type: "decimal", allowNull: true, precision: 20, scale: 10 },
|
|
75
76
|
{ name: "providerRequestId", type: "string", allowNull: true },
|
|
@@ -0,0 +1,66 @@
|
|
|
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
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var add_cache_input_price_exports = {};
|
|
28
|
+
__export(add_cache_input_price_exports, {
|
|
29
|
+
default: () => AddCacheInputPriceToModelPrices
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(add_cache_input_price_exports);
|
|
32
|
+
var import_server = require("@nocobase/server");
|
|
33
|
+
class AddCacheInputPriceToModelPrices extends import_server.Migration {
|
|
34
|
+
on = "beforeLoad";
|
|
35
|
+
async up() {
|
|
36
|
+
await this.addDecimalColumn("aiApiModelPrices", "cacheInputPricePerMillionTokens", false, 0);
|
|
37
|
+
await this.addDecimalColumn("aiApiUsageRecords", "cacheInputPricePerMillionTokens", true);
|
|
38
|
+
}
|
|
39
|
+
async down() {
|
|
40
|
+
await this.removeColumn("aiApiUsageRecords", "cacheInputPricePerMillionTokens");
|
|
41
|
+
await this.removeColumn("aiApiModelPrices", "cacheInputPricePerMillionTokens");
|
|
42
|
+
}
|
|
43
|
+
async addDecimalColumn(collectionName, columnName, allowNull, defaultValue) {
|
|
44
|
+
const collection = this.db.getCollection(collectionName);
|
|
45
|
+
if (!collection || !await collection.existsInDb()) return;
|
|
46
|
+
const tableName = collection.getTableNameWithSchema();
|
|
47
|
+
if (await this.columnExists(tableName, columnName)) return;
|
|
48
|
+
await this.queryInterface.addColumn(tableName, columnName, {
|
|
49
|
+
type: "DECIMAL(20,10)",
|
|
50
|
+
allowNull,
|
|
51
|
+
...defaultValue === void 0 ? {} : { defaultValue }
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
async removeColumn(collectionName, columnName) {
|
|
55
|
+
const collection = this.db.getCollection(collectionName);
|
|
56
|
+
if (!collection || !await collection.existsInDb()) return;
|
|
57
|
+
const tableName = collection.getTableNameWithSchema();
|
|
58
|
+
if (await this.columnExists(tableName, columnName)) {
|
|
59
|
+
await this.queryInterface.removeColumn(tableName, columnName);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async columnExists(tableName, columnName) {
|
|
63
|
+
const columns = await this.queryInterface.describeTable(tableName);
|
|
64
|
+
return Object.prototype.hasOwnProperty.call(columns, columnName);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -91,6 +91,22 @@ async function authenticateBearer(ctx) {
|
|
|
91
91
|
ctx.body = (0, import_openai_format.toOpenAIError)(401, "Invalid or expired API key", "invalid_request_error", "invalid_api_key");
|
|
92
92
|
return false;
|
|
93
93
|
}
|
|
94
|
+
if (jwt.blacklist) {
|
|
95
|
+
let blocked = false;
|
|
96
|
+
try {
|
|
97
|
+
blocked = await jwt.blacklist.has(decoded.jti ?? token);
|
|
98
|
+
} catch (err) {
|
|
99
|
+
ctx.log.error("AI API token blacklist check failed:", err);
|
|
100
|
+
ctx.status = 401;
|
|
101
|
+
ctx.body = (0, import_openai_format.toOpenAIError)(401, "Unable to verify API key status", "server_error");
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
if (blocked) {
|
|
105
|
+
ctx.status = 401;
|
|
106
|
+
ctx.body = (0, import_openai_format.toOpenAIError)(401, "API key has been revoked", "invalid_request_error", "invalid_api_key");
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
94
110
|
if (!decoded.roleName) {
|
|
95
111
|
ctx.status = 401;
|
|
96
112
|
ctx.body = (0, import_openai_format.toOpenAIError)(
|
|
@@ -34,6 +34,7 @@ var import_resolve_service = require("../utils/resolve-service");
|
|
|
34
34
|
var import_user_permissions = require("../utils/user-permissions");
|
|
35
35
|
var import_request_cache = require("../utils/request-cache");
|
|
36
36
|
var import_usage = require("../usage");
|
|
37
|
+
var import_billing = require("../billing");
|
|
37
38
|
async function handleEmbeddings(ctx, plugin) {
|
|
38
39
|
const body = ctx.request.body;
|
|
39
40
|
if (!(body == null ? void 0 : body.model)) {
|
|
@@ -93,6 +94,7 @@ async function handleEmbeddings(ctx, plugin) {
|
|
|
93
94
|
return;
|
|
94
95
|
}
|
|
95
96
|
const { service, modelId } = resolved;
|
|
97
|
+
await (0, import_billing.prepareLlmBilling)(ctx, resolved);
|
|
96
98
|
if (service.enabled === false) {
|
|
97
99
|
ctx.status = 404;
|
|
98
100
|
ctx.body = (0, import_openai_format.toOpenAIError)(
|
|
@@ -144,10 +146,18 @@ async function handleEmbeddings(ctx, plugin) {
|
|
|
144
146
|
// The specific embedding model
|
|
145
147
|
});
|
|
146
148
|
const embeddingModel = embeddingProvider.createEmbedding();
|
|
149
|
+
(0, import_billing.markLlmProviderAttempted)(ctx);
|
|
147
150
|
const vectors = await embeddingModel.embedDocuments(inputs);
|
|
151
|
+
const estimatedInputTokens = Math.ceil(inputs.reduce((sum, s) => sum + s.length, 0) / 4);
|
|
152
|
+
const usage = {
|
|
153
|
+
prompt_tokens: estimatedInputTokens,
|
|
154
|
+
completion_tokens: 0,
|
|
155
|
+
total_tokens: estimatedInputTokens
|
|
156
|
+
};
|
|
157
|
+
(0, import_usage.setAiApiUsageResult)(ctx, usage);
|
|
158
|
+
await (0, import_billing.finalizeLlmBilling)(ctx, usage, true);
|
|
148
159
|
ctx.status = 200;
|
|
149
160
|
ctx.set("Content-Type", "application/json");
|
|
150
|
-
(0, import_usage.setAiApiUsageUnavailable)(ctx);
|
|
151
161
|
ctx.body = (0, import_openai_format.toOpenAIEmbeddingsResponse)({
|
|
152
162
|
model: body.model,
|
|
153
163
|
embeddings: vectors,
|
package/dist/server/usage.js
CHANGED
|
@@ -176,6 +176,7 @@ async function finishUsageRecord(ctx, id, startedAt, status) {
|
|
|
176
176
|
quotaPolicyId: billing.quotaPolicyId ?? null,
|
|
177
177
|
groupId: billing.groupId ?? null,
|
|
178
178
|
inputPricePerMillionTokens: billing.inputPricePerMillionTokens ?? null,
|
|
179
|
+
cacheInputPricePerMillionTokens: billing.cacheInputPricePerMillionTokens ?? null,
|
|
179
180
|
outputPricePerMillionTokens: billing.outputPricePerMillionTokens ?? null,
|
|
180
181
|
fixedCostPerRequest: billing.fixedCostPerRequest ?? null,
|
|
181
182
|
providerRequestId: usageResult.providerRequestId ?? null,
|
|
@@ -26,6 +26,8 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
26
26
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
27
|
var direct_llm_context_exports = {};
|
|
28
28
|
__export(direct_llm_context_exports, {
|
|
29
|
+
DEFAULT_CONTEXT_WINDOW: () => DEFAULT_CONTEXT_WINDOW,
|
|
30
|
+
DEFAULT_MAX_COMPLETION_TOKENS: () => DEFAULT_MAX_COMPLETION_TOKENS,
|
|
29
31
|
DirectLlmContextError: () => DirectLlmContextError,
|
|
30
32
|
parseImageDimensions: () => parseImageDimensions,
|
|
31
33
|
prepareDirectLlmContext: () => prepareDirectLlmContext
|
|
@@ -226,18 +228,15 @@ function messagesWithTurns(messages, turns) {
|
|
|
226
228
|
const retainedMessages = new Set(turns.flat());
|
|
227
229
|
return messages.filter((message) => isInstruction(message) || retainedMessages.has(message));
|
|
228
230
|
}
|
|
231
|
+
const DEFAULT_CONTEXT_WINDOW = 128e3;
|
|
232
|
+
const DEFAULT_MAX_COMPLETION_TOKENS = 8192;
|
|
229
233
|
async function loadModelMetadata(ctx, serviceName, modelId) {
|
|
230
234
|
const row = await ctx.db.getRepository("aiApiModelMetadata").findOne({
|
|
231
235
|
filter: { llmService: serviceName, model: modelId, enabled: true }
|
|
232
236
|
});
|
|
233
|
-
const
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
throw new DirectLlmContextError(
|
|
237
|
-
"model_context_metadata_not_configured",
|
|
238
|
-
`Context metadata is not configured for '${serviceName}/${modelId}'. Configure context window and max completion tokens.`
|
|
239
|
-
);
|
|
240
|
-
}
|
|
237
|
+
const config = await (0, import_request_cache.getAiApiConfig)(ctx);
|
|
238
|
+
const contextWindow = positiveInteger(getValue(row, "contextWindow")) ?? positiveInteger(getValue(config, "defaultContextWindow")) ?? DEFAULT_CONTEXT_WINDOW;
|
|
239
|
+
const maxCompletionTokens = positiveInteger(getValue(row, "maxCompletionTokens")) ?? positiveInteger(getValue(config, "defaultMaxCompletionTokens")) ?? DEFAULT_MAX_COMPLETION_TOKENS;
|
|
241
240
|
const systemPromptValue = getValue(row, "systemPrompt");
|
|
242
241
|
const systemPrompt = typeof systemPromptValue === "string" ? systemPromptValue.trim() : "";
|
|
243
242
|
return { contextWindow, maxCompletionTokens, ...systemPrompt ? { systemPrompt } : {} };
|
|
@@ -315,6 +314,8 @@ async function prepareDirectLlmContext(ctx, options) {
|
|
|
315
314
|
}
|
|
316
315
|
// Annotate the CommonJS export names for ESM import in node:
|
|
317
316
|
0 && (module.exports = {
|
|
317
|
+
DEFAULT_CONTEXT_WINDOW,
|
|
318
|
+
DEFAULT_MAX_COMPLETION_TOKENS,
|
|
318
319
|
DirectLlmContextError,
|
|
319
320
|
parseImageDimensions,
|
|
320
321
|
prepareDirectLlmContext
|
|
@@ -55,6 +55,7 @@ function requireNonNegativeIntegerOrNull(value, field) {
|
|
|
55
55
|
}
|
|
56
56
|
async function validateModelPrice(db, model) {
|
|
57
57
|
requireNonNegativeDecimal(model.get("inputPricePerMillionTokens"), "inputPricePerMillionTokens");
|
|
58
|
+
requireNonNegativeDecimal(model.get("cacheInputPricePerMillionTokens") ?? 0, "cacheInputPricePerMillionTokens");
|
|
58
59
|
requireNonNegativeDecimal(model.get("outputPricePerMillionTokens"), "outputPricePerMillionTokens");
|
|
59
60
|
requireNonNegativeDecimal(model.get("fixedCostPerRequest") ?? 0, "fixedCostPerRequest");
|
|
60
61
|
const effectiveFrom = new Date(String(model.get("effectiveFrom")));
|
package/package.json
CHANGED
package/src/client/index.tsx
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
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 } from './plugin';
|
|
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 } from './plugin';
|
|
@@ -1,12 +1,12 @@
|
|
|
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
|
-
import { ModelConstructor } from '@nocobase/flow-engine';
|
|
11
|
-
|
|
12
|
-
export default {} as Record<string, ModelConstructor>;
|
|
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
|
+
import { ModelConstructor } from '@nocobase/flow-engine';
|
|
11
|
+
|
|
12
|
+
export default {} as Record<string, ModelConstructor>;
|
|
@@ -28,6 +28,7 @@ interface ModelPrice {
|
|
|
28
28
|
model: string;
|
|
29
29
|
currency: string;
|
|
30
30
|
inputPricePerMillionTokens: string;
|
|
31
|
+
cacheInputPricePerMillionTokens: string;
|
|
31
32
|
outputPricePerMillionTokens: string;
|
|
32
33
|
fixedCostPerRequest: string;
|
|
33
34
|
effectiveFrom: string;
|
|
@@ -95,6 +96,7 @@ export default function ModelPricingPage() {
|
|
|
95
96
|
form.setFieldsValue({
|
|
96
97
|
currency: 'USD',
|
|
97
98
|
inputPricePerMillionTokens: '0',
|
|
99
|
+
cacheInputPricePerMillionTokens: '0',
|
|
98
100
|
outputPricePerMillionTokens: '0',
|
|
99
101
|
fixedCostPerRequest: '0',
|
|
100
102
|
effectiveFrom: dayjs(),
|
|
@@ -182,6 +184,12 @@ export default function ModelPricingPage() {
|
|
|
182
184
|
{ title: t('LLM service'), dataIndex: 'llmService', key: 'llmService', width: 180 },
|
|
183
185
|
{ title: t('Model'), dataIndex: 'model', key: 'model', width: 180 },
|
|
184
186
|
{ title: t('Input price / 1M'), dataIndex: 'inputPricePerMillionTokens', key: 'inputPrice', width: 150 },
|
|
187
|
+
{
|
|
188
|
+
title: t('Cache input price / 1M'),
|
|
189
|
+
dataIndex: 'cacheInputPricePerMillionTokens',
|
|
190
|
+
key: 'cacheInputPrice',
|
|
191
|
+
width: 170,
|
|
192
|
+
},
|
|
185
193
|
{ title: t('Output price / 1M'), dataIndex: 'outputPricePerMillionTokens', key: 'outputPrice', width: 150 },
|
|
186
194
|
{ title: t('Fixed request cost'), dataIndex: 'fixedCostPerRequest', key: 'fixedCost', width: 150 },
|
|
187
195
|
{ title: t('Currency'), dataIndex: 'currency', key: 'currency', width: 90 },
|
|
@@ -260,6 +268,13 @@ export default function ModelPricingPage() {
|
|
|
260
268
|
<Form.Item name="inputPricePerMillionTokens" label={t('Input price / 1M')} rules={[{ required: true }]}>
|
|
261
269
|
<InputNumber min={0} stringMode style={{ width: '100%' }} />
|
|
262
270
|
</Form.Item>
|
|
271
|
+
<Form.Item
|
|
272
|
+
name="cacheInputPricePerMillionTokens"
|
|
273
|
+
label={t('Cache input price / 1M')}
|
|
274
|
+
rules={[{ required: true }]}
|
|
275
|
+
>
|
|
276
|
+
<InputNumber min={0} stringMode style={{ width: '100%' }} />
|
|
277
|
+
</Form.Item>
|
|
263
278
|
<Form.Item name="outputPricePerMillionTokens" label={t('Output price / 1M')} rules={[{ required: true }]}>
|
|
264
279
|
<InputNumber min={0} stringMode style={{ width: '100%' }} />
|
|
265
280
|
</Form.Item>
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
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 * from './server';
|
|
11
|
-
export { default } from './server';
|
|
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 * from './server';
|
|
11
|
+
export { default } from './server';
|