@llmops/core 0.1.5 → 0.1.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/dist/{bun-sqlite-dialect-Bp2qbl5F.cjs → bun-sqlite-dialect-CYbkeI0s.cjs} +1 -1
- package/dist/db/index.cjs +1 -1
- package/dist/db/index.d.cts +1 -1
- package/dist/db/index.d.mts +1 -1
- package/dist/db/index.mjs +1 -1
- package/dist/{db-eEfIe5dO.cjs → db-C_u1BuaR.cjs} +11 -2
- package/dist/{db-DSzwrW4p.mjs → db-D78x_Elf.mjs} +9 -0
- package/dist/{index-BO7DYWFs.d.cts → index-CCfvTBvD.d.cts} +43 -25
- package/dist/{index-mUSLoeGU.d.mts → index-CzGmPK4Q.d.mts} +43 -25
- package/dist/index.cjs +107 -18
- package/dist/index.d.cts +67 -5
- package/dist/index.d.mts +276 -214
- package/dist/index.mjs +107 -18
- package/dist/{node-sqlite-dialect-b2V910TJ.cjs → node-sqlite-dialect-BSbNUAzj.cjs} +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as object, C as zod_default, D as boolean, E as array, M as string, N as union, O as literal, P as unknown, S as workspaceSettingsSchema, T as any, _ as llmRequestsSchema, a as matchType, b as variantVersionsSchema, c as parsePartialTableData, d as validateTableData, f as SCHEMA_METADATA, g as environmentsSchema, h as environmentSecretsSchema, i as getMigrations, j as record, k as number, l as parseTableData, m as configsSchema, n as createDatabaseFromConnection, o as runAutoMigrations, p as configVariantsSchema, r as detectDatabaseType, s as logger, t as createDatabase, u as validatePartialTableData, v as schemas, w as _enum, x as variantsSchema, y as targetingRulesSchema } from "./db-
|
|
1
|
+
import { A as object, C as zod_default, D as boolean, E as array, M as string, N as union, O as literal, P as unknown, S as workspaceSettingsSchema, T as any, _ as llmRequestsSchema, a as matchType, b as variantVersionsSchema, c as parsePartialTableData, d as validateTableData, f as SCHEMA_METADATA, g as environmentsSchema, h as environmentSecretsSchema, i as getMigrations, j as record, k as number, l as parseTableData, m as configsSchema, n as createDatabaseFromConnection, o as runAutoMigrations, p as configVariantsSchema, r as detectDatabaseType, s as logger, t as createDatabase, u as validatePartialTableData, v as schemas, w as _enum, x as variantsSchema, y as targetingRulesSchema } from "./db-D78x_Elf.mjs";
|
|
2
2
|
import gateway from "@llmops/gateway";
|
|
3
3
|
import { sql } from "kysely";
|
|
4
4
|
import * as fs from "node:fs/promises";
|
|
@@ -1283,7 +1283,8 @@ const createConfigVariantDataLayer = (db) => {
|
|
|
1283
1283
|
return {
|
|
1284
1284
|
...versionData,
|
|
1285
1285
|
configId: resolvedConfigId,
|
|
1286
|
-
variantId: configVariant.variantId
|
|
1286
|
+
variantId: configVariant.variantId,
|
|
1287
|
+
environmentId
|
|
1287
1288
|
};
|
|
1288
1289
|
}
|
|
1289
1290
|
};
|
|
@@ -1453,6 +1454,7 @@ const insertLLMRequestSchema = zod_default.object({
|
|
|
1453
1454
|
requestId: zod_default.string().uuid(),
|
|
1454
1455
|
configId: zod_default.string().uuid().nullable().optional(),
|
|
1455
1456
|
variantId: zod_default.string().uuid().nullable().optional(),
|
|
1457
|
+
environmentId: zod_default.string().uuid().nullable().optional(),
|
|
1456
1458
|
provider: zod_default.string(),
|
|
1457
1459
|
model: zod_default.string(),
|
|
1458
1460
|
promptTokens: zod_default.number().int().default(0),
|
|
@@ -1476,17 +1478,24 @@ const listRequestsSchema = zod_default.object({
|
|
|
1476
1478
|
limit: zod_default.number().int().positive().max(1e3).default(100),
|
|
1477
1479
|
offset: zod_default.number().int().nonnegative().default(0),
|
|
1478
1480
|
configId: zod_default.string().uuid().optional(),
|
|
1481
|
+
variantId: zod_default.string().uuid().optional(),
|
|
1482
|
+
environmentId: zod_default.string().uuid().optional(),
|
|
1479
1483
|
provider: zod_default.string().optional(),
|
|
1480
1484
|
model: zod_default.string().optional(),
|
|
1481
1485
|
startDate: zod_default.date().optional(),
|
|
1482
|
-
endDate: zod_default.date().optional()
|
|
1486
|
+
endDate: zod_default.date().optional(),
|
|
1487
|
+
tags: zod_default.record(zod_default.string(), zod_default.array(zod_default.string())).optional()
|
|
1483
1488
|
});
|
|
1484
1489
|
/**
|
|
1485
|
-
* Schema for date range queries
|
|
1490
|
+
* Schema for date range queries with optional filters
|
|
1486
1491
|
*/
|
|
1487
1492
|
const dateRangeSchema = zod_default.object({
|
|
1488
1493
|
startDate: zod_default.date(),
|
|
1489
|
-
endDate: zod_default.date()
|
|
1494
|
+
endDate: zod_default.date(),
|
|
1495
|
+
configId: zod_default.string().uuid().optional(),
|
|
1496
|
+
variantId: zod_default.string().uuid().optional(),
|
|
1497
|
+
environmentId: zod_default.string().uuid().optional(),
|
|
1498
|
+
tags: zod_default.record(zod_default.string(), zod_default.array(zod_default.string())).optional()
|
|
1490
1499
|
});
|
|
1491
1500
|
/**
|
|
1492
1501
|
* Schema for cost summary with grouping
|
|
@@ -1494,6 +1503,10 @@ const dateRangeSchema = zod_default.object({
|
|
|
1494
1503
|
const costSummarySchema = zod_default.object({
|
|
1495
1504
|
startDate: zod_default.date(),
|
|
1496
1505
|
endDate: zod_default.date(),
|
|
1506
|
+
configId: zod_default.string().uuid().optional(),
|
|
1507
|
+
variantId: zod_default.string().uuid().optional(),
|
|
1508
|
+
environmentId: zod_default.string().uuid().optional(),
|
|
1509
|
+
tags: zod_default.record(zod_default.string(), zod_default.array(zod_default.string())).optional(),
|
|
1497
1510
|
groupBy: zod_default.enum([
|
|
1498
1511
|
"day",
|
|
1499
1512
|
"hour",
|
|
@@ -1523,6 +1536,7 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
1523
1536
|
requestId: req.requestId,
|
|
1524
1537
|
configId: req.configId ?? null,
|
|
1525
1538
|
variantId: req.variantId ?? null,
|
|
1539
|
+
environmentId: req.environmentId ?? null,
|
|
1526
1540
|
provider: req.provider,
|
|
1527
1541
|
model: req.model,
|
|
1528
1542
|
promptTokens: req.promptTokens,
|
|
@@ -1554,6 +1568,7 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
1554
1568
|
requestId: req.requestId,
|
|
1555
1569
|
configId: req.configId ?? null,
|
|
1556
1570
|
variantId: req.variantId ?? null,
|
|
1571
|
+
environmentId: req.environmentId ?? null,
|
|
1557
1572
|
provider: req.provider,
|
|
1558
1573
|
model: req.model,
|
|
1559
1574
|
promptTokens: req.promptTokens,
|
|
@@ -1576,14 +1591,43 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
1576
1591
|
listRequests: async (params) => {
|
|
1577
1592
|
const result = await listRequestsSchema.safeParseAsync(params || {});
|
|
1578
1593
|
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
1579
|
-
const { limit, offset, configId, provider, model, startDate, endDate } = result.data;
|
|
1594
|
+
const { limit, offset, configId, variantId, environmentId, provider, model, startDate, endDate, tags } = result.data;
|
|
1595
|
+
console.log("[listRequests] Parsed filters:", {
|
|
1596
|
+
configId,
|
|
1597
|
+
variantId,
|
|
1598
|
+
environmentId,
|
|
1599
|
+
provider,
|
|
1600
|
+
model
|
|
1601
|
+
});
|
|
1580
1602
|
let baseQuery = db.selectFrom("llm_requests");
|
|
1581
|
-
if (configId)
|
|
1603
|
+
if (configId) {
|
|
1604
|
+
console.log("[listRequests] Adding configId filter:", configId);
|
|
1605
|
+
baseQuery = baseQuery.where("configId", "=", configId);
|
|
1606
|
+
}
|
|
1607
|
+
if (variantId) {
|
|
1608
|
+
console.log("[listRequests] Adding variantId filter:", variantId);
|
|
1609
|
+
baseQuery = baseQuery.where("variantId", "=", variantId);
|
|
1610
|
+
}
|
|
1611
|
+
if (environmentId) {
|
|
1612
|
+
console.log("[listRequests] Adding environmentId filter:", environmentId);
|
|
1613
|
+
baseQuery = baseQuery.where("environmentId", "=", environmentId);
|
|
1614
|
+
}
|
|
1582
1615
|
if (provider) baseQuery = baseQuery.where("provider", "=", provider);
|
|
1583
1616
|
if (model) baseQuery = baseQuery.where("model", "=", model);
|
|
1584
1617
|
if (startDate) baseQuery = baseQuery.where(sql`${col("createdAt")} >= ${startDate.toISOString()}`);
|
|
1585
1618
|
if (endDate) baseQuery = baseQuery.where(sql`${col("createdAt")} <= ${endDate.toISOString()}`);
|
|
1586
|
-
|
|
1619
|
+
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
1620
|
+
if (values.length === 0) continue;
|
|
1621
|
+
if (values.length === 1) baseQuery = baseQuery.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
1622
|
+
else {
|
|
1623
|
+
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
1624
|
+
baseQuery = baseQuery.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
const countQuery = baseQuery.select(sql`COUNT(*)`.as("total"));
|
|
1628
|
+
console.log("[listRequests] Count SQL:", countQuery.compile().sql);
|
|
1629
|
+
console.log("[listRequests] Count params:", countQuery.compile().parameters);
|
|
1630
|
+
const countResult = await countQuery.executeTakeFirst();
|
|
1587
1631
|
const total = Number(countResult?.total ?? 0);
|
|
1588
1632
|
return {
|
|
1589
1633
|
data: await baseQuery.selectAll().orderBy("createdAt", "desc").limit(limit).offset(offset).execute(),
|
|
@@ -1598,8 +1642,8 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
1598
1642
|
getTotalCost: async (params) => {
|
|
1599
1643
|
const result = await dateRangeSchema.safeParseAsync(params);
|
|
1600
1644
|
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
1601
|
-
const { startDate, endDate } = result.data;
|
|
1602
|
-
|
|
1645
|
+
const { startDate, endDate, configId, variantId, environmentId, tags } = result.data;
|
|
1646
|
+
let query = db.selectFrom("llm_requests").select([
|
|
1603
1647
|
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
1604
1648
|
sql`COALESCE(SUM(${col("inputCost")}), 0)`.as("totalInputCost"),
|
|
1605
1649
|
sql`COALESCE(SUM(${col("outputCost")}), 0)`.as("totalOutputCost"),
|
|
@@ -1607,7 +1651,19 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
1607
1651
|
sql`COALESCE(SUM(${col("completionTokens")}), 0)`.as("totalCompletionTokens"),
|
|
1608
1652
|
sql`COALESCE(SUM(${col("totalTokens")}), 0)`.as("totalTokens"),
|
|
1609
1653
|
sql`COUNT(*)`.as("requestCount")
|
|
1610
|
-
]).where(sql`${col("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col("createdAt")} <= ${endDate.toISOString()}`)
|
|
1654
|
+
]).where(sql`${col("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col("createdAt")} <= ${endDate.toISOString()}`);
|
|
1655
|
+
if (configId) query = query.where("configId", "=", configId);
|
|
1656
|
+
if (variantId) query = query.where("variantId", "=", variantId);
|
|
1657
|
+
if (environmentId) query = query.where("environmentId", "=", environmentId);
|
|
1658
|
+
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
1659
|
+
if (values.length === 0) continue;
|
|
1660
|
+
if (values.length === 1) query = query.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
1661
|
+
else {
|
|
1662
|
+
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
1663
|
+
query = query.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
return await query.executeTakeFirst();
|
|
1611
1667
|
},
|
|
1612
1668
|
getCostByModel: async (params) => {
|
|
1613
1669
|
const result = await dateRangeSchema.safeParseAsync(params);
|
|
@@ -1673,18 +1729,31 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
1673
1729
|
getCostSummary: async (params) => {
|
|
1674
1730
|
const result = await costSummarySchema.safeParseAsync(params);
|
|
1675
1731
|
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
1676
|
-
const { startDate, endDate, groupBy } = result.data;
|
|
1677
|
-
|
|
1732
|
+
const { startDate, endDate, groupBy, configId, variantId, environmentId, tags } = result.data;
|
|
1733
|
+
let baseQuery = db.selectFrom("llm_requests").where(sql`${col("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col("createdAt")} <= ${endDate.toISOString()}`);
|
|
1734
|
+
if (configId) baseQuery = baseQuery.where("configId", "=", configId);
|
|
1735
|
+
if (variantId) baseQuery = baseQuery.where("variantId", "=", variantId);
|
|
1736
|
+
if (environmentId) baseQuery = baseQuery.where("environmentId", "=", environmentId);
|
|
1737
|
+
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
1738
|
+
if (values.length === 0) continue;
|
|
1739
|
+
if (values.length === 1) baseQuery = baseQuery.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
1740
|
+
else {
|
|
1741
|
+
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
1742
|
+
baseQuery = baseQuery.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1678
1745
|
switch (groupBy) {
|
|
1679
1746
|
case "day": return baseQuery.select([
|
|
1680
1747
|
sql`DATE(${col("createdAt")})`.as("groupKey"),
|
|
1681
1748
|
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
1682
|
-
sql`COUNT(*)`.as("requestCount")
|
|
1749
|
+
sql`COUNT(*)`.as("requestCount"),
|
|
1750
|
+
sql`COALESCE(SUM(${col("totalTokens")}), 0)`.as("totalTokens")
|
|
1683
1751
|
]).groupBy(sql`DATE(${col("createdAt")})`).orderBy(sql`DATE(${col("createdAt")})`, "asc").execute();
|
|
1684
1752
|
case "hour": return baseQuery.select([
|
|
1685
1753
|
sql`DATE_TRUNC('hour', ${col("createdAt")})`.as("groupKey"),
|
|
1686
1754
|
sql`COALESCE(SUM(${col("cost")}), 0)`.as("totalCost"),
|
|
1687
|
-
sql`COUNT(*)`.as("requestCount")
|
|
1755
|
+
sql`COUNT(*)`.as("requestCount"),
|
|
1756
|
+
sql`COALESCE(SUM(${col("totalTokens")}), 0)`.as("totalTokens")
|
|
1688
1757
|
]).groupBy(sql`DATE_TRUNC('hour', ${col("createdAt")})`).orderBy(sql`DATE_TRUNC('hour', ${col("createdAt")})`, "asc").execute();
|
|
1689
1758
|
case "model": return baseQuery.select([
|
|
1690
1759
|
sql`${col("provider")} || '/' || ${col("model")}`.as("groupKey"),
|
|
@@ -1711,8 +1780,8 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
1711
1780
|
getRequestStats: async (params) => {
|
|
1712
1781
|
const result = await dateRangeSchema.safeParseAsync(params);
|
|
1713
1782
|
if (!result.success) throw new LLMOpsError(`Invalid parameters: ${result.error.message}`);
|
|
1714
|
-
const { startDate, endDate } = result.data;
|
|
1715
|
-
|
|
1783
|
+
const { startDate, endDate, configId, variantId, environmentId, tags } = result.data;
|
|
1784
|
+
let query = db.selectFrom("llm_requests").select([
|
|
1716
1785
|
sql`COUNT(*)`.as("totalRequests"),
|
|
1717
1786
|
sql`COUNT(CASE WHEN ${col("statusCode")} >= 200 AND ${col("statusCode")} < 300 THEN 1 END)`.as("successfulRequests"),
|
|
1718
1787
|
sql`COUNT(CASE WHEN ${col("statusCode")} >= 400 THEN 1 END)`.as("failedRequests"),
|
|
@@ -1720,7 +1789,27 @@ const createLLMRequestsDataLayer = (db) => {
|
|
|
1720
1789
|
sql`AVG(${col("latencyMs")})`.as("avgLatencyMs"),
|
|
1721
1790
|
sql`MAX(${col("latencyMs")})`.as("maxLatencyMs"),
|
|
1722
1791
|
sql`MIN(${col("latencyMs")})`.as("minLatencyMs")
|
|
1723
|
-
]).where(sql`${col("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col("createdAt")} <= ${endDate.toISOString()}`)
|
|
1792
|
+
]).where(sql`${col("createdAt")} >= ${startDate.toISOString()}`).where(sql`${col("createdAt")} <= ${endDate.toISOString()}`);
|
|
1793
|
+
if (configId) query = query.where("configId", "=", configId);
|
|
1794
|
+
if (variantId) query = query.where("variantId", "=", variantId);
|
|
1795
|
+
if (environmentId) query = query.where("environmentId", "=", environmentId);
|
|
1796
|
+
if (tags && Object.keys(tags).length > 0) for (const [key, values] of Object.entries(tags)) {
|
|
1797
|
+
if (values.length === 0) continue;
|
|
1798
|
+
if (values.length === 1) query = query.where(sql`${col("tags")}->>${key} = ${values[0]}`);
|
|
1799
|
+
else {
|
|
1800
|
+
const valueList = sql.join(values.map((v) => sql`${v}`));
|
|
1801
|
+
query = query.where(sql`${col("tags")}->>${key} IN (${valueList})`);
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
return await query.executeTakeFirst();
|
|
1805
|
+
},
|
|
1806
|
+
getDistinctTags: async () => {
|
|
1807
|
+
return (await sql`
|
|
1808
|
+
SELECT DISTINCT key, value
|
|
1809
|
+
FROM llm_requests, jsonb_each_text(tags) AS t(key, value)
|
|
1810
|
+
WHERE tags != '{}'::jsonb
|
|
1811
|
+
ORDER BY key, value
|
|
1812
|
+
`.execute(db)).rows;
|
|
1724
1813
|
}
|
|
1725
1814
|
};
|
|
1726
1815
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llmops/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Core LLMOps functionality and utilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"hono": "^4.10.7",
|
|
52
52
|
"kysely": "^0.28.8",
|
|
53
53
|
"pino": "^10.1.0",
|
|
54
|
-
"@llmops/gateway": "^0.1.
|
|
54
|
+
"@llmops/gateway": "^0.1.6"
|
|
55
55
|
},
|
|
56
56
|
"scripts": {
|
|
57
57
|
"build": "tsdown",
|