@ax-llm/ax 12.0.19 → 12.0.21

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/index.cjs CHANGED
@@ -162,10 +162,15 @@ __export(index_exports, {
162
162
  axAITogetherDefaultConfig: () => axAITogetherDefaultConfig,
163
163
  axBaseAIDefaultConfig: () => axBaseAIDefaultConfig,
164
164
  axBaseAIDefaultCreativeConfig: () => axBaseAIDefaultCreativeConfig,
165
+ axCheckMetricsHealth: () => axCheckMetricsHealth,
165
166
  axCreateDefaultLogger: () => axCreateDefaultLogger,
166
167
  axCreateDefaultTextLogger: () => axCreateDefaultTextLogger,
167
168
  axCreateOptimizerLogger: () => axCreateOptimizerLogger,
169
+ axDefaultMetricsConfig: () => axDefaultMetricsConfig,
168
170
  axDefaultOptimizerLogger: () => axDefaultOptimizerLogger,
171
+ axDefaultOptimizerMetricsConfig: () => axDefaultOptimizerMetricsConfig,
172
+ axGetMetricsConfig: () => axGetMetricsConfig,
173
+ axGetOptimizerMetricsConfig: () => axGetOptimizerMetricsConfig,
169
174
  axGlobals: () => axGlobals,
170
175
  axModelInfoAnthropic: () => axModelInfoAnthropic,
171
176
  axModelInfoCohere: () => axModelInfoCohere,
@@ -181,6 +186,8 @@ __export(index_exports, {
181
186
  axModelInfoTogether: () => axModelInfoTogether,
182
187
  axSpanAttributes: () => axSpanAttributes,
183
188
  axSpanEvents: () => axSpanEvents,
189
+ axUpdateMetricsConfig: () => axUpdateMetricsConfig,
190
+ axUpdateOptimizerMetricsConfig: () => axUpdateOptimizerMetricsConfig,
184
191
  axValidateChatRequestMessage: () => axValidateChatRequestMessage,
185
192
  axValidateChatResponseResult: () => axValidateChatResponseResult,
186
193
  f: () => f,
@@ -770,6 +777,16 @@ var apiCall = async (api, json) => {
770
777
  var import_crypto2 = __toESM(require("crypto"), 1);
771
778
  var import_api2 = require("@opentelemetry/api");
772
779
 
780
+ // dsp/globals.ts
781
+ var axGlobals = {
782
+ signatureStrict: true,
783
+ // Controls reservedNames enforcement in signature parsing/validation
784
+ tracer: void 0,
785
+ // Global OpenTelemetry tracer for all AI operations
786
+ meter: void 0
787
+ // Global OpenTelemetry meter for metrics collection
788
+ };
789
+
773
790
  // trace/trace.ts
774
791
  var axSpanAttributes = {
775
792
  // LLM
@@ -1203,6 +1220,326 @@ var logResponseDelta = (delta, logger = defaultLogger) => {
1203
1220
  logger(delta, { tags: ["responseContent"] });
1204
1221
  };
1205
1222
 
1223
+ // ai/metrics.ts
1224
+ var sanitizeLabels = (labels) => {
1225
+ const sanitized = {};
1226
+ for (const [key, value] of Object.entries(labels)) {
1227
+ if (value !== void 0 && value !== null) {
1228
+ const stringValue = String(value);
1229
+ sanitized[key] = stringValue.length > 100 ? stringValue.substring(0, 100) : stringValue;
1230
+ }
1231
+ }
1232
+ return sanitized;
1233
+ };
1234
+ var globalAIMetricsInstruments;
1235
+ var getOrCreateAIMetricsInstruments = (meter) => {
1236
+ if (globalAIMetricsInstruments) {
1237
+ return globalAIMetricsInstruments;
1238
+ }
1239
+ if (meter) {
1240
+ globalAIMetricsInstruments = createMetricsInstruments(meter);
1241
+ return globalAIMetricsInstruments;
1242
+ }
1243
+ return void 0;
1244
+ };
1245
+ var createMetricsInstruments = (meter) => {
1246
+ return {
1247
+ latencyHistogram: meter.createHistogram("ax_llm_request_duration_ms", {
1248
+ description: "Duration of LLM requests in milliseconds",
1249
+ unit: "ms"
1250
+ }),
1251
+ errorCounter: meter.createCounter("ax_llm_errors_total", {
1252
+ description: "Total number of LLM request errors"
1253
+ }),
1254
+ requestCounter: meter.createCounter("ax_llm_requests_total", {
1255
+ description: "Total number of LLM requests"
1256
+ }),
1257
+ tokenCounter: meter.createCounter("ax_llm_tokens_total", {
1258
+ description: "Total number of LLM tokens consumed"
1259
+ }),
1260
+ inputTokenCounter: meter.createCounter("ax_llm_input_tokens_total", {
1261
+ description: "Total number of input/prompt tokens consumed"
1262
+ }),
1263
+ outputTokenCounter: meter.createCounter("ax_llm_output_tokens_total", {
1264
+ description: "Total number of output/completion tokens generated"
1265
+ }),
1266
+ errorRateGauge: meter.createGauge("ax_llm_error_rate", {
1267
+ description: "Current error rate as a percentage (0-100)"
1268
+ }),
1269
+ meanLatencyGauge: meter.createGauge("ax_llm_mean_latency_ms", {
1270
+ description: "Mean latency of LLM requests in milliseconds",
1271
+ unit: "ms"
1272
+ }),
1273
+ p95LatencyGauge: meter.createGauge("ax_llm_p95_latency_ms", {
1274
+ description: "95th percentile latency of LLM requests in milliseconds",
1275
+ unit: "ms"
1276
+ }),
1277
+ p99LatencyGauge: meter.createGauge("ax_llm_p99_latency_ms", {
1278
+ description: "99th percentile latency of LLM requests in milliseconds",
1279
+ unit: "ms"
1280
+ }),
1281
+ streamingRequestsCounter: meter.createCounter(
1282
+ "ax_llm_streaming_requests_total",
1283
+ {
1284
+ description: "Total number of streaming LLM requests"
1285
+ }
1286
+ ),
1287
+ functionCallsCounter: meter.createCounter("ax_llm_function_calls_total", {
1288
+ description: "Total number of function/tool calls made"
1289
+ }),
1290
+ functionCallLatencyHistogram: meter.createHistogram(
1291
+ "ax_llm_function_call_latency_ms",
1292
+ {
1293
+ description: "Latency of function calls in milliseconds",
1294
+ unit: "ms"
1295
+ }
1296
+ ),
1297
+ requestSizeHistogram: meter.createHistogram("ax_llm_request_size_bytes", {
1298
+ description: "Size of LLM request payloads in bytes",
1299
+ unit: "By"
1300
+ }),
1301
+ responseSizeHistogram: meter.createHistogram("ax_llm_response_size_bytes", {
1302
+ description: "Size of LLM response payloads in bytes",
1303
+ unit: "By"
1304
+ }),
1305
+ temperatureGauge: meter.createGauge("ax_llm_temperature_gauge", {
1306
+ description: "Temperature setting used for LLM requests"
1307
+ }),
1308
+ maxTokensGauge: meter.createGauge("ax_llm_max_tokens_gauge", {
1309
+ description: "Maximum tokens setting used for LLM requests"
1310
+ }),
1311
+ estimatedCostCounter: meter.createCounter("ax_llm_estimated_cost_total", {
1312
+ description: "Estimated cost of LLM requests in USD",
1313
+ unit: "$"
1314
+ }),
1315
+ promptLengthHistogram: meter.createHistogram("ax_llm_prompt_length_chars", {
1316
+ description: "Length of prompts in characters"
1317
+ }),
1318
+ contextWindowUsageGauge: meter.createGauge(
1319
+ "ax_llm_context_window_usage_ratio",
1320
+ {
1321
+ description: "Context window utilization ratio (0-1)"
1322
+ }
1323
+ ),
1324
+ timeoutsCounter: meter.createCounter("ax_llm_timeouts_total", {
1325
+ description: "Total number of timed out LLM requests"
1326
+ }),
1327
+ abortsCounter: meter.createCounter("ax_llm_aborts_total", {
1328
+ description: "Total number of aborted LLM requests"
1329
+ }),
1330
+ thinkingBudgetUsageCounter: meter.createCounter(
1331
+ "ax_llm_thinking_budget_usage_total",
1332
+ {
1333
+ description: "Total thinking budget tokens used"
1334
+ }
1335
+ ),
1336
+ multimodalRequestsCounter: meter.createCounter(
1337
+ "ax_llm_multimodal_requests_total",
1338
+ {
1339
+ description: "Total number of multimodal requests (with images/audio)"
1340
+ }
1341
+ )
1342
+ };
1343
+ };
1344
+ var recordLatencyMetric = (instruments, type, duration, aiService, model) => {
1345
+ try {
1346
+ if (instruments.latencyHistogram) {
1347
+ const labels = sanitizeLabels({
1348
+ operation: type,
1349
+ ai_service: aiService,
1350
+ ...model ? { model } : {}
1351
+ });
1352
+ instruments.latencyHistogram.record(duration, labels);
1353
+ }
1354
+ } catch (error) {
1355
+ console.warn("Failed to record latency metric:", error);
1356
+ }
1357
+ };
1358
+ var recordLatencyStatsMetrics = (instruments, type, meanLatency, p95Latency, p99Latency, aiService, model) => {
1359
+ const labels = {
1360
+ operation: type,
1361
+ ai_service: aiService,
1362
+ ...model ? { model } : {}
1363
+ };
1364
+ if (instruments.meanLatencyGauge) {
1365
+ instruments.meanLatencyGauge.record(meanLatency, labels);
1366
+ }
1367
+ if (instruments.p95LatencyGauge) {
1368
+ instruments.p95LatencyGauge.record(p95Latency, labels);
1369
+ }
1370
+ if (instruments.p99LatencyGauge) {
1371
+ instruments.p99LatencyGauge.record(p99Latency, labels);
1372
+ }
1373
+ };
1374
+ var recordErrorMetric = (instruments, type, aiService, model) => {
1375
+ try {
1376
+ if (instruments.errorCounter) {
1377
+ const labels = sanitizeLabels({
1378
+ operation: type,
1379
+ ai_service: aiService,
1380
+ ...model ? { model } : {}
1381
+ });
1382
+ instruments.errorCounter.add(1, labels);
1383
+ }
1384
+ } catch (error) {
1385
+ console.warn("Failed to record error metric:", error);
1386
+ }
1387
+ };
1388
+ var recordErrorRateMetric = (instruments, type, errorRate, aiService, model) => {
1389
+ if (instruments.errorRateGauge) {
1390
+ instruments.errorRateGauge.record(errorRate * 100, {
1391
+ // Convert to percentage
1392
+ operation: type,
1393
+ ai_service: aiService,
1394
+ ...model ? { model } : {}
1395
+ });
1396
+ }
1397
+ };
1398
+ var recordRequestMetric = (instruments, type, aiService, model) => {
1399
+ if (instruments.requestCounter) {
1400
+ instruments.requestCounter.add(1, {
1401
+ operation: type,
1402
+ ai_service: aiService,
1403
+ ...model ? { model } : {}
1404
+ });
1405
+ }
1406
+ };
1407
+ var recordTokenMetric = (instruments, type, tokens, aiService, model) => {
1408
+ try {
1409
+ const labels = sanitizeLabels({
1410
+ ai_service: aiService,
1411
+ ...model ? { model } : {}
1412
+ });
1413
+ if (instruments.tokenCounter) {
1414
+ instruments.tokenCounter.add(tokens, {
1415
+ token_type: type,
1416
+ ...labels
1417
+ });
1418
+ }
1419
+ if (type === "input" && instruments.inputTokenCounter) {
1420
+ instruments.inputTokenCounter.add(tokens, labels);
1421
+ }
1422
+ if (type === "output" && instruments.outputTokenCounter) {
1423
+ instruments.outputTokenCounter.add(tokens, labels);
1424
+ }
1425
+ } catch (error) {
1426
+ console.warn("Failed to record token metric:", error);
1427
+ }
1428
+ };
1429
+ var recordStreamingRequestMetric = (instruments, type, isStreaming, aiService, model) => {
1430
+ if (isStreaming && instruments.streamingRequestsCounter) {
1431
+ instruments.streamingRequestsCounter.add(1, {
1432
+ operation: type,
1433
+ ai_service: aiService,
1434
+ ...model ? { model } : {}
1435
+ });
1436
+ }
1437
+ };
1438
+ var recordFunctionCallMetric = (instruments, functionName, latency, aiService, model) => {
1439
+ const labels = {
1440
+ function_name: functionName,
1441
+ ...aiService ? { ai_service: aiService } : {},
1442
+ ...model ? { model } : {}
1443
+ };
1444
+ if (instruments.functionCallsCounter) {
1445
+ instruments.functionCallsCounter.add(1, labels);
1446
+ }
1447
+ if (latency && instruments.functionCallLatencyHistogram) {
1448
+ instruments.functionCallLatencyHistogram.record(latency, labels);
1449
+ }
1450
+ };
1451
+ var recordRequestSizeMetric = (instruments, type, sizeBytes, aiService, model) => {
1452
+ if (instruments.requestSizeHistogram) {
1453
+ instruments.requestSizeHistogram.record(sizeBytes, {
1454
+ operation: type,
1455
+ ai_service: aiService,
1456
+ ...model ? { model } : {}
1457
+ });
1458
+ }
1459
+ };
1460
+ var recordResponseSizeMetric = (instruments, type, sizeBytes, aiService, model) => {
1461
+ if (instruments.responseSizeHistogram) {
1462
+ instruments.responseSizeHistogram.record(sizeBytes, {
1463
+ operation: type,
1464
+ ai_service: aiService,
1465
+ ...model ? { model } : {}
1466
+ });
1467
+ }
1468
+ };
1469
+ var recordModelConfigMetrics = (instruments, temperature, maxTokens, aiService, model) => {
1470
+ const labels = {
1471
+ ...aiService ? { ai_service: aiService } : {},
1472
+ ...model ? { model } : {}
1473
+ };
1474
+ if (temperature !== void 0 && instruments.temperatureGauge) {
1475
+ instruments.temperatureGauge.record(temperature, labels);
1476
+ }
1477
+ if (maxTokens !== void 0 && instruments.maxTokensGauge) {
1478
+ instruments.maxTokensGauge.record(maxTokens, labels);
1479
+ }
1480
+ };
1481
+ var recordEstimatedCostMetric = (instruments, type, costUSD, aiService, model) => {
1482
+ if (instruments.estimatedCostCounter) {
1483
+ instruments.estimatedCostCounter.add(costUSD, {
1484
+ operation: type,
1485
+ ai_service: aiService,
1486
+ ...model ? { model } : {}
1487
+ });
1488
+ }
1489
+ };
1490
+ var recordPromptLengthMetric = (instruments, lengthChars, aiService, model) => {
1491
+ if (instruments.promptLengthHistogram) {
1492
+ instruments.promptLengthHistogram.record(lengthChars, {
1493
+ ai_service: aiService,
1494
+ ...model ? { model } : {}
1495
+ });
1496
+ }
1497
+ };
1498
+ var recordContextWindowUsageMetric = (instruments, usageRatio, aiService, model) => {
1499
+ if (instruments.contextWindowUsageGauge) {
1500
+ instruments.contextWindowUsageGauge.record(usageRatio, {
1501
+ ai_service: aiService,
1502
+ ...model ? { model } : {}
1503
+ });
1504
+ }
1505
+ };
1506
+ var recordTimeoutMetric = (instruments, type, aiService, model) => {
1507
+ if (instruments.timeoutsCounter) {
1508
+ instruments.timeoutsCounter.add(1, {
1509
+ operation: type,
1510
+ ai_service: aiService,
1511
+ ...model ? { model } : {}
1512
+ });
1513
+ }
1514
+ };
1515
+ var recordAbortMetric = (instruments, type, aiService, model) => {
1516
+ if (instruments.abortsCounter) {
1517
+ instruments.abortsCounter.add(1, {
1518
+ operation: type,
1519
+ ai_service: aiService,
1520
+ ...model ? { model } : {}
1521
+ });
1522
+ }
1523
+ };
1524
+ var recordThinkingBudgetUsageMetric = (instruments, tokensUsed, aiService, model) => {
1525
+ if (instruments.thinkingBudgetUsageCounter) {
1526
+ instruments.thinkingBudgetUsageCounter.add(tokensUsed, {
1527
+ ai_service: aiService,
1528
+ ...model ? { model } : {}
1529
+ });
1530
+ }
1531
+ };
1532
+ var recordMultimodalRequestMetric = (instruments, hasImages, hasAudio, aiService, model) => {
1533
+ if ((hasImages || hasAudio) && instruments.multimodalRequestsCounter) {
1534
+ instruments.multimodalRequestsCounter.add(1, {
1535
+ ai_service: aiService,
1536
+ has_images: hasImages.toString(),
1537
+ has_audio: hasAudio.toString(),
1538
+ ...model ? { model } : {}
1539
+ });
1540
+ }
1541
+ };
1542
+
1206
1543
  // ai/base.ts
1207
1544
  var axBaseAIDefaultConfig = () => structuredClone({
1208
1545
  temperature: 0,
@@ -1233,7 +1570,8 @@ var AxBaseAI = class {
1233
1570
  this.apiURL = apiURL;
1234
1571
  this.headers = headers;
1235
1572
  this.supportFor = supportFor;
1236
- this.tracer = options.tracer;
1573
+ this.tracer = options.tracer ?? axGlobals.tracer;
1574
+ this.meter = options.meter ?? axGlobals.meter;
1237
1575
  this.modelInfo = modelInfo;
1238
1576
  this.models = models;
1239
1577
  this.id = import_crypto2.default.randomUUID();
@@ -1252,6 +1590,7 @@ var AxBaseAI = class {
1252
1590
  rt;
1253
1591
  fetch;
1254
1592
  tracer;
1593
+ meter;
1255
1594
  timeout;
1256
1595
  excludeContentFromTrace;
1257
1596
  models;
@@ -1298,6 +1637,9 @@ var AxBaseAI = class {
1298
1637
  }
1299
1638
  }
1300
1639
  };
1640
+ getMetricsInstruments() {
1641
+ return getOrCreateAIMetricsInstruments(this.meter);
1642
+ }
1301
1643
  setName(name) {
1302
1644
  this.name = name;
1303
1645
  }
@@ -1315,7 +1657,8 @@ var AxBaseAI = class {
1315
1657
  this.rt = options.rateLimiter;
1316
1658
  this.fetch = options.fetch;
1317
1659
  this.timeout = options.timeout;
1318
- this.tracer = options.tracer;
1660
+ this.tracer = options.tracer ?? axGlobals.tracer;
1661
+ this.meter = options.meter ?? axGlobals.meter;
1319
1662
  this.excludeContentFromTrace = options.excludeContentFromTrace;
1320
1663
  this.abortSignal = options.abortSignal;
1321
1664
  this.logger = options.logger ?? defaultLogger2;
@@ -1326,6 +1669,7 @@ var AxBaseAI = class {
1326
1669
  rateLimiter: this.rt,
1327
1670
  fetch: this.fetch,
1328
1671
  tracer: this.tracer,
1672
+ meter: this.meter,
1329
1673
  timeout: this.timeout,
1330
1674
  excludeContentFromTrace: this.excludeContentFromTrace,
1331
1675
  abortSignal: this.abortSignal,
@@ -1390,6 +1734,20 @@ var AxBaseAI = class {
1390
1734
  metrics.mean = metrics.samples.reduce((a, b) => a + b, 0) / metrics.samples.length;
1391
1735
  metrics.p95 = this.calculatePercentile(metrics.samples, 95);
1392
1736
  metrics.p99 = this.calculatePercentile(metrics.samples, 99);
1737
+ const metricsInstruments = this.getMetricsInstruments();
1738
+ if (metricsInstruments) {
1739
+ const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1740
+ recordLatencyMetric(metricsInstruments, type, duration, this.name, model);
1741
+ recordLatencyStatsMetrics(
1742
+ metricsInstruments,
1743
+ type,
1744
+ metrics.mean,
1745
+ metrics.p95,
1746
+ metrics.p99,
1747
+ this.name,
1748
+ model
1749
+ );
1750
+ }
1393
1751
  }
1394
1752
  // Method to update error metrics
1395
1753
  updateErrorMetrics(type, isError) {
@@ -1399,6 +1757,319 @@ var AxBaseAI = class {
1399
1757
  metrics.count++;
1400
1758
  }
1401
1759
  metrics.rate = metrics.count / metrics.total;
1760
+ const metricsInstruments = this.getMetricsInstruments();
1761
+ if (metricsInstruments) {
1762
+ const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1763
+ recordRequestMetric(metricsInstruments, type, this.name, model);
1764
+ if (isError) {
1765
+ recordErrorMetric(metricsInstruments, type, this.name, model);
1766
+ }
1767
+ recordErrorRateMetric(
1768
+ metricsInstruments,
1769
+ type,
1770
+ metrics.rate,
1771
+ this.name,
1772
+ model
1773
+ );
1774
+ }
1775
+ }
1776
+ // Method to record token usage metrics
1777
+ recordTokenUsage(modelUsage) {
1778
+ const metricsInstruments = this.getMetricsInstruments();
1779
+ if (metricsInstruments && modelUsage?.tokens) {
1780
+ const { promptTokens, completionTokens, totalTokens, thoughtsTokens } = modelUsage.tokens;
1781
+ if (promptTokens) {
1782
+ recordTokenMetric(
1783
+ metricsInstruments,
1784
+ "input",
1785
+ promptTokens,
1786
+ this.name,
1787
+ modelUsage.model
1788
+ );
1789
+ }
1790
+ if (completionTokens) {
1791
+ recordTokenMetric(
1792
+ metricsInstruments,
1793
+ "output",
1794
+ completionTokens,
1795
+ this.name,
1796
+ modelUsage.model
1797
+ );
1798
+ }
1799
+ if (totalTokens) {
1800
+ recordTokenMetric(
1801
+ metricsInstruments,
1802
+ "total",
1803
+ totalTokens,
1804
+ this.name,
1805
+ modelUsage.model
1806
+ );
1807
+ }
1808
+ if (thoughtsTokens) {
1809
+ recordTokenMetric(
1810
+ metricsInstruments,
1811
+ "thoughts",
1812
+ thoughtsTokens,
1813
+ this.name,
1814
+ modelUsage.model
1815
+ );
1816
+ }
1817
+ }
1818
+ }
1819
+ // Helper method to calculate request size in bytes
1820
+ calculateRequestSize(req) {
1821
+ try {
1822
+ return new TextEncoder().encode(JSON.stringify(req)).length;
1823
+ } catch {
1824
+ return 0;
1825
+ }
1826
+ }
1827
+ // Helper method to calculate response size in bytes
1828
+ calculateResponseSize(response) {
1829
+ try {
1830
+ return new TextEncoder().encode(JSON.stringify(response)).length;
1831
+ } catch {
1832
+ return 0;
1833
+ }
1834
+ }
1835
+ // Helper method to detect multimodal content
1836
+ detectMultimodalContent(req) {
1837
+ let hasImages = false;
1838
+ let hasAudio = false;
1839
+ if (req.chatPrompt && Array.isArray(req.chatPrompt)) {
1840
+ for (const message of req.chatPrompt) {
1841
+ if (message.role === "user" && Array.isArray(message.content)) {
1842
+ for (const part of message.content) {
1843
+ if (part.type === "image") {
1844
+ hasImages = true;
1845
+ } else if (part.type === "audio") {
1846
+ hasAudio = true;
1847
+ }
1848
+ }
1849
+ }
1850
+ }
1851
+ }
1852
+ return { hasImages, hasAudio };
1853
+ }
1854
+ // Helper method to calculate prompt length
1855
+ calculatePromptLength(req) {
1856
+ let totalLength = 0;
1857
+ if (req.chatPrompt && Array.isArray(req.chatPrompt)) {
1858
+ for (const message of req.chatPrompt) {
1859
+ if (message.role === "system" || message.role === "assistant") {
1860
+ if (message.content) {
1861
+ totalLength += message.content.length;
1862
+ }
1863
+ } else if (message.role === "user") {
1864
+ if (typeof message.content === "string") {
1865
+ totalLength += message.content.length;
1866
+ } else if (Array.isArray(message.content)) {
1867
+ for (const part of message.content) {
1868
+ if (part.type === "text") {
1869
+ totalLength += part.text.length;
1870
+ }
1871
+ }
1872
+ }
1873
+ } else if (message.role === "function") {
1874
+ if (message.result) {
1875
+ totalLength += message.result.length;
1876
+ }
1877
+ }
1878
+ }
1879
+ }
1880
+ return totalLength;
1881
+ }
1882
+ // Helper method to calculate context window usage
1883
+ calculateContextWindowUsage(model, modelUsage) {
1884
+ if (!modelUsage?.tokens?.promptTokens) return 0;
1885
+ const modelInfo = this.modelInfo.find(
1886
+ (info) => info.name === model
1887
+ );
1888
+ if (!modelInfo?.contextWindow) return 0;
1889
+ return modelUsage.tokens.promptTokens / modelInfo.contextWindow;
1890
+ }
1891
+ // Helper method to estimate cost
1892
+ estimateCost(model, modelUsage) {
1893
+ if (!modelUsage?.tokens) return 0;
1894
+ const modelInfo = this.modelInfo.find(
1895
+ (info) => info.name === model
1896
+ );
1897
+ if (!modelInfo || !modelInfo.promptTokenCostPer1M && !modelInfo.completionTokenCostPer1M)
1898
+ return 0;
1899
+ const { promptTokens = 0, completionTokens = 0 } = modelUsage.tokens;
1900
+ const promptCostPer1M = modelInfo.promptTokenCostPer1M || 0;
1901
+ const completionCostPer1M = modelInfo.completionTokenCostPer1M || 0;
1902
+ return promptTokens * promptCostPer1M / 1e6 + completionTokens * completionCostPer1M / 1e6;
1903
+ }
1904
+ // Helper method to estimate cost by model name
1905
+ estimateCostByName(modelName, modelUsage) {
1906
+ if (!modelUsage?.tokens) return 0;
1907
+ const modelInfo = this.modelInfo.find((info) => info.name === modelName);
1908
+ if (!modelInfo || !modelInfo.promptTokenCostPer1M && !modelInfo.completionTokenCostPer1M)
1909
+ return 0;
1910
+ const { promptTokens = 0, completionTokens = 0 } = modelUsage.tokens;
1911
+ const promptCostPer1M = modelInfo.promptTokenCostPer1M || 0;
1912
+ const completionCostPer1M = modelInfo.completionTokenCostPer1M || 0;
1913
+ return promptTokens * promptCostPer1M / 1e6 + completionTokens * completionCostPer1M / 1e6;
1914
+ }
1915
+ // Helper method to record function call metrics
1916
+ recordFunctionCallMetrics(functionCalls, model) {
1917
+ const metricsInstruments = this.getMetricsInstruments();
1918
+ if (!metricsInstruments || !functionCalls) return;
1919
+ for (const call of functionCalls) {
1920
+ if (call && typeof call === "object" && "function" in call && call.function && typeof call.function === "object" && "name" in call.function) {
1921
+ recordFunctionCallMetric(
1922
+ metricsInstruments,
1923
+ call.function.name,
1924
+ void 0,
1925
+ // latency would need to be tracked separately
1926
+ this.name,
1927
+ model
1928
+ );
1929
+ }
1930
+ }
1931
+ }
1932
+ // Helper method to record timeout metrics
1933
+ recordTimeoutMetric(type) {
1934
+ const metricsInstruments = this.getMetricsInstruments();
1935
+ if (metricsInstruments) {
1936
+ const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1937
+ recordTimeoutMetric(metricsInstruments, type, this.name, model);
1938
+ }
1939
+ }
1940
+ // Helper method to record abort metrics
1941
+ recordAbortMetric(type) {
1942
+ const metricsInstruments = this.getMetricsInstruments();
1943
+ if (metricsInstruments) {
1944
+ const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1945
+ recordAbortMetric(metricsInstruments, type, this.name, model);
1946
+ }
1947
+ }
1948
+ // Comprehensive method to record all chat-related metrics
1949
+ recordChatMetrics(req, options, result) {
1950
+ const metricsInstruments = this.getMetricsInstruments();
1951
+ if (!metricsInstruments) return;
1952
+ const model = this.lastUsedChatModel;
1953
+ const modelConfig = this.lastUsedModelConfig;
1954
+ const isStreaming = modelConfig?.stream ?? false;
1955
+ recordStreamingRequestMetric(
1956
+ metricsInstruments,
1957
+ "chat",
1958
+ isStreaming,
1959
+ this.name,
1960
+ model
1961
+ );
1962
+ const { hasImages, hasAudio } = this.detectMultimodalContent(req);
1963
+ recordMultimodalRequestMetric(
1964
+ metricsInstruments,
1965
+ hasImages,
1966
+ hasAudio,
1967
+ this.name,
1968
+ model
1969
+ );
1970
+ const promptLength = this.calculatePromptLength(req);
1971
+ recordPromptLengthMetric(metricsInstruments, promptLength, this.name, model);
1972
+ recordModelConfigMetrics(
1973
+ metricsInstruments,
1974
+ modelConfig?.temperature,
1975
+ modelConfig?.maxTokens,
1976
+ this.name,
1977
+ model
1978
+ );
1979
+ if (options?.thinkingTokenBudget && this.modelUsage?.tokens?.thoughtsTokens) {
1980
+ recordThinkingBudgetUsageMetric(
1981
+ metricsInstruments,
1982
+ this.modelUsage.tokens.thoughtsTokens,
1983
+ this.name,
1984
+ model
1985
+ );
1986
+ }
1987
+ const requestSize = this.calculateRequestSize(req);
1988
+ recordRequestSizeMetric(
1989
+ metricsInstruments,
1990
+ "chat",
1991
+ requestSize,
1992
+ this.name,
1993
+ model
1994
+ );
1995
+ if (result && !isStreaming) {
1996
+ const chatResponse = result;
1997
+ const responseSize = this.calculateResponseSize(chatResponse);
1998
+ recordResponseSizeMetric(
1999
+ metricsInstruments,
2000
+ "chat",
2001
+ responseSize,
2002
+ this.name,
2003
+ model
2004
+ );
2005
+ if (chatResponse.results) {
2006
+ for (const chatResult of chatResponse.results) {
2007
+ if (chatResult.functionCalls) {
2008
+ this.recordFunctionCallMetrics(
2009
+ chatResult.functionCalls,
2010
+ this.lastUsedChatModel
2011
+ );
2012
+ }
2013
+ }
2014
+ }
2015
+ const contextUsage = this.calculateContextWindowUsage(
2016
+ this.lastUsedChatModel,
2017
+ chatResponse.modelUsage
2018
+ );
2019
+ if (contextUsage > 0) {
2020
+ recordContextWindowUsageMetric(
2021
+ metricsInstruments,
2022
+ contextUsage,
2023
+ this.name,
2024
+ model
2025
+ );
2026
+ }
2027
+ const estimatedCost = this.estimateCost(
2028
+ this.lastUsedChatModel,
2029
+ chatResponse.modelUsage
2030
+ );
2031
+ if (estimatedCost > 0) {
2032
+ recordEstimatedCostMetric(
2033
+ metricsInstruments,
2034
+ "chat",
2035
+ estimatedCost,
2036
+ this.name,
2037
+ model
2038
+ );
2039
+ }
2040
+ }
2041
+ }
2042
+ // Comprehensive method to record all embed-related metrics
2043
+ recordEmbedMetrics(req, result) {
2044
+ const metricsInstruments = this.getMetricsInstruments();
2045
+ if (!metricsInstruments) return;
2046
+ const model = this.lastUsedEmbedModel;
2047
+ const requestSize = this.calculateRequestSize(req);
2048
+ recordRequestSizeMetric(
2049
+ metricsInstruments,
2050
+ "embed",
2051
+ requestSize,
2052
+ this.name,
2053
+ model
2054
+ );
2055
+ const responseSize = this.calculateResponseSize(result);
2056
+ recordResponseSizeMetric(
2057
+ metricsInstruments,
2058
+ "embed",
2059
+ responseSize,
2060
+ this.name,
2061
+ model
2062
+ );
2063
+ const estimatedCost = this.estimateCostByName(model, result.modelUsage);
2064
+ if (estimatedCost > 0) {
2065
+ recordEstimatedCostMetric(
2066
+ metricsInstruments,
2067
+ "embed",
2068
+ estimatedCost,
2069
+ this.name,
2070
+ model
2071
+ );
2072
+ }
1402
2073
  }
1403
2074
  // Public method to get metrics
1404
2075
  getMetrics() {
@@ -1407,16 +2078,27 @@ var AxBaseAI = class {
1407
2078
  async chat(req, options) {
1408
2079
  const startTime = performance.now();
1409
2080
  let isError = false;
2081
+ let result;
1410
2082
  try {
1411
- const result = await this._chat1(req, options);
2083
+ result = await this._chat1(req, options);
1412
2084
  return result;
1413
2085
  } catch (error) {
1414
2086
  isError = true;
2087
+ if (error instanceof Error) {
2088
+ if (error.message.includes("timeout") || error.name === "TimeoutError") {
2089
+ this.recordTimeoutMetric("chat");
2090
+ } else if (error.message.includes("abort") || error.name === "AbortError") {
2091
+ this.recordAbortMetric("chat");
2092
+ }
2093
+ }
1415
2094
  throw error;
1416
2095
  } finally {
1417
2096
  const duration = performance.now() - startTime;
1418
2097
  this.updateLatencyMetrics("chat", duration);
1419
2098
  this.updateErrorMetrics("chat", isError);
2099
+ if (!isError) {
2100
+ this.recordChatMetrics(req, options, result);
2101
+ }
1420
2102
  }
1421
2103
  }
1422
2104
  async _chat1(req, options) {
@@ -1563,6 +2245,7 @@ var AxBaseAI = class {
1563
2245
  }
1564
2246
  }
1565
2247
  this.modelUsage = res2.modelUsage;
2248
+ this.recordTokenUsage(res2.modelUsage);
1566
2249
  if (span?.isRecording()) {
1567
2250
  setChatResponseEvents(res2, span, this.excludeContentFromTrace);
1568
2251
  }
@@ -1605,6 +2288,7 @@ var AxBaseAI = class {
1605
2288
  }
1606
2289
  if (res.modelUsage) {
1607
2290
  this.modelUsage = res.modelUsage;
2291
+ this.recordTokenUsage(res.modelUsage);
1608
2292
  }
1609
2293
  if (span?.isRecording()) {
1610
2294
  setChatResponseEvents(res, span, this.excludeContentFromTrace);
@@ -1621,15 +2305,27 @@ var AxBaseAI = class {
1621
2305
  async embed(req, options) {
1622
2306
  const startTime = performance.now();
1623
2307
  let isError = false;
2308
+ let result;
1624
2309
  try {
1625
- return this._embed1(req, options);
2310
+ result = await this._embed1(req, options);
2311
+ return result;
1626
2312
  } catch (error) {
1627
2313
  isError = true;
2314
+ if (error instanceof Error) {
2315
+ if (error.message.includes("timeout") || error.name === "TimeoutError") {
2316
+ this.recordTimeoutMetric("embed");
2317
+ } else if (error.message.includes("abort") || error.name === "AbortError") {
2318
+ this.recordAbortMetric("embed");
2319
+ }
2320
+ }
1628
2321
  throw error;
1629
2322
  } finally {
1630
2323
  const duration = performance.now() - startTime;
1631
2324
  this.updateLatencyMetrics("embed", duration);
1632
2325
  this.updateErrorMetrics("embed", isError);
2326
+ if (!isError) {
2327
+ this.recordEmbedMetrics(req, result);
2328
+ }
1633
2329
  }
1634
2330
  }
1635
2331
  async _embed1(req, options) {
@@ -1704,6 +2400,7 @@ var AxBaseAI = class {
1704
2400
  }
1705
2401
  }
1706
2402
  this.embedModelUsage = res.modelUsage;
2403
+ this.recordTokenUsage(res.modelUsage);
1707
2404
  if (span?.isRecording() && res.modelUsage?.tokens) {
1708
2405
  span.addEvent(axSpanEvents.GEN_AI_USAGE, {
1709
2406
  [axSpanAttributes.LLM_USAGE_INPUT_TOKENS]: res.modelUsage.tokens.promptTokens,
@@ -8036,88 +8733,577 @@ function createFunctionConfig(functionList, definedFunctionCall, firstStep) {
8036
8733
  return { functions, functionCall };
8037
8734
  }
8038
8735
 
8039
- // dsp/processResponse.ts
8040
- var import_web5 = require("stream/web");
8041
-
8042
- // ai/util.ts
8043
- function mergeFunctionCalls(functionCalls, functionCallDeltas) {
8044
- for (const _fc of functionCallDeltas) {
8045
- const fc = functionCalls.find((fc2) => fc2.id === _fc.id);
8046
- if (fc) {
8047
- if (typeof _fc.function.name == "string" && _fc.function.name.length > 0) {
8048
- fc.function.name += _fc.function.name;
8049
- }
8050
- if (typeof _fc.function.params == "string" && _fc.function.params.length > 0) {
8051
- fc.function.params += _fc.function.params;
8052
- }
8053
- if (typeof _fc.function.params == "object") {
8054
- fc.function.params = _fc.function.params;
8055
- }
8056
- } else {
8057
- functionCalls.push(_fc);
8058
- }
8059
- }
8060
- }
8061
-
8062
- // dsp/sig.ts
8063
- var import_crypto3 = require("crypto");
8064
-
8065
- // dsp/globals.ts
8066
- var axGlobals = {
8067
- signatureStrict: true
8068
- // Controls reservedNames enforcement in signature parsing/validation
8736
+ // dsp/metrics.ts
8737
+ var axDefaultMetricsConfig = {
8738
+ enabled: true,
8739
+ enabledCategories: [
8740
+ "generation",
8741
+ "streaming",
8742
+ "functions",
8743
+ "errors",
8744
+ "performance"
8745
+ ],
8746
+ maxLabelLength: 100,
8747
+ samplingRate: 1
8069
8748
  };
8070
-
8071
- // dsp/parser.ts
8072
- var SignatureValidationError = class extends Error {
8073
- constructor(message, position, context3, suggestion) {
8074
- super(message);
8075
- this.position = position;
8076
- this.context = context3;
8077
- this.suggestion = suggestion;
8078
- this.name = "SignatureValidationError";
8749
+ var globalGenMetricsInstruments;
8750
+ var getOrCreateGenMetricsInstruments = (meter) => {
8751
+ if (globalGenMetricsInstruments) {
8752
+ return globalGenMetricsInstruments;
8079
8753
  }
8754
+ const activeMeter = meter ?? axGlobals.meter;
8755
+ if (activeMeter) {
8756
+ globalGenMetricsInstruments = createGenMetricsInstruments(activeMeter);
8757
+ return globalGenMetricsInstruments;
8758
+ }
8759
+ return void 0;
8080
8760
  };
8081
- var SignatureParser = class {
8082
- input;
8083
- position;
8084
- currentFieldName = null;
8085
- currentSection = "description";
8086
- constructor(input) {
8087
- this.input = input.trim();
8088
- this.position = 0;
8089
- if (!this.input) {
8090
- throw new SignatureValidationError(
8091
- "Empty signature provided",
8092
- 0,
8093
- "",
8094
- 'A signature must contain at least input and output fields separated by "->". Example: "userQuery:string -> aiResponse:string"'
8095
- );
8096
- }
8761
+ var axCheckMetricsHealth = () => {
8762
+ const issues = [];
8763
+ if (!axGlobals.meter) {
8764
+ issues.push("Global meter not initialized");
8097
8765
  }
8098
- parse() {
8099
- try {
8100
- this.skipWhitespace();
8101
- const optionalDesc = this.parseParsedString();
8102
- this.skipWhitespace();
8103
- this.currentSection = "inputs";
8104
- const inputs = this.parseFieldList(
8105
- this.parseInputField.bind(this),
8106
- "input"
8107
- );
8108
- this.skipWhitespace();
8109
- if (this.position >= this.input.length) {
8110
- throw new SignatureValidationError(
8111
- "Incomplete signature: Missing output section",
8112
- this.position,
8113
- this.getErrorContext(),
8114
- 'Add "->" followed by output fields. Example: "-> responseText:string"'
8115
- );
8116
- }
8117
- this.expectArrow();
8118
- this.skipWhitespace();
8119
- if (this.position >= this.input.length) {
8120
- throw new SignatureValidationError(
8766
+ if (!globalGenMetricsInstruments && axGlobals.meter) {
8767
+ issues.push("Metrics instruments not created despite available meter");
8768
+ }
8769
+ return {
8770
+ healthy: issues.length === 0,
8771
+ issues
8772
+ };
8773
+ };
8774
+ var createGenMetricsInstruments = (meter) => {
8775
+ return {
8776
+ // Generation flow metrics
8777
+ // Note: Histogram buckets should be configured at the exporter level
8778
+ // Recommended buckets: [1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000] ms
8779
+ generationLatencyHistogram: meter.createHistogram(
8780
+ "ax_gen_generation_duration_ms",
8781
+ {
8782
+ description: "End-to-end duration of AxGen generation requests",
8783
+ unit: "ms"
8784
+ }
8785
+ ),
8786
+ generationRequestsCounter: meter.createCounter(
8787
+ "ax_gen_generation_requests_total",
8788
+ {
8789
+ description: "Total number of AxGen generation requests"
8790
+ }
8791
+ ),
8792
+ generationErrorsCounter: meter.createCounter(
8793
+ "ax_gen_generation_errors_total",
8794
+ {
8795
+ description: "Total number of failed AxGen generations"
8796
+ }
8797
+ ),
8798
+ // Multi-step flow metrics
8799
+ multiStepGenerationsCounter: meter.createCounter(
8800
+ "ax_gen_multistep_generations_total",
8801
+ {
8802
+ description: "Total number of generations that required multiple steps"
8803
+ }
8804
+ ),
8805
+ stepsPerGenerationHistogram: meter.createHistogram(
8806
+ "ax_gen_steps_per_generation",
8807
+ {
8808
+ description: "Number of steps taken per generation"
8809
+ }
8810
+ ),
8811
+ maxStepsReachedCounter: meter.createCounter(
8812
+ "ax_gen_max_steps_reached_total",
8813
+ {
8814
+ description: "Total number of generations that hit max steps limit"
8815
+ }
8816
+ ),
8817
+ // Error correction metrics
8818
+ validationErrorsCounter: meter.createCounter(
8819
+ "ax_gen_validation_errors_total",
8820
+ {
8821
+ description: "Total number of validation errors encountered"
8822
+ }
8823
+ ),
8824
+ assertionErrorsCounter: meter.createCounter(
8825
+ "ax_gen_assertion_errors_total",
8826
+ {
8827
+ description: "Total number of assertion errors encountered"
8828
+ }
8829
+ ),
8830
+ errorCorrectionAttemptsHistogram: meter.createHistogram(
8831
+ "ax_gen_error_correction_attempts",
8832
+ {
8833
+ description: "Number of error correction attempts per generation"
8834
+ }
8835
+ ),
8836
+ errorCorrectionSuccessCounter: meter.createCounter(
8837
+ "ax_gen_error_correction_success_total",
8838
+ {
8839
+ description: "Total number of successful error corrections"
8840
+ }
8841
+ ),
8842
+ errorCorrectionFailureCounter: meter.createCounter(
8843
+ "ax_gen_error_correction_failure_total",
8844
+ {
8845
+ description: "Total number of failed error corrections"
8846
+ }
8847
+ ),
8848
+ maxRetriesReachedCounter: meter.createCounter(
8849
+ "ax_gen_max_retries_reached_total",
8850
+ {
8851
+ description: "Total number of generations that hit max retries limit"
8852
+ }
8853
+ ),
8854
+ // Function calling metrics
8855
+ functionsEnabledGenerationsCounter: meter.createCounter(
8856
+ "ax_gen_functions_enabled_generations_total",
8857
+ {
8858
+ description: "Total number of generations with functions enabled"
8859
+ }
8860
+ ),
8861
+ functionCallStepsCounter: meter.createCounter(
8862
+ "ax_gen_function_call_steps_total",
8863
+ {
8864
+ description: "Total number of steps that included function calls"
8865
+ }
8866
+ ),
8867
+ functionsExecutedPerGenerationHistogram: meter.createHistogram(
8868
+ "ax_gen_functions_executed_per_generation",
8869
+ {
8870
+ description: "Number of unique functions executed per generation"
8871
+ }
8872
+ ),
8873
+ functionErrorCorrectionCounter: meter.createCounter(
8874
+ "ax_gen_function_error_correction_total",
8875
+ {
8876
+ description: "Total number of function-related error corrections"
8877
+ }
8878
+ ),
8879
+ // Field processing metrics
8880
+ fieldProcessorsExecutedCounter: meter.createCounter(
8881
+ "ax_gen_field_processors_executed_total",
8882
+ {
8883
+ description: "Total number of field processors executed"
8884
+ }
8885
+ ),
8886
+ streamingFieldProcessorsExecutedCounter: meter.createCounter(
8887
+ "ax_gen_streaming_field_processors_executed_total",
8888
+ {
8889
+ description: "Total number of streaming field processors executed"
8890
+ }
8891
+ ),
8892
+ // Streaming specific metrics
8893
+ streamingGenerationsCounter: meter.createCounter(
8894
+ "ax_gen_streaming_generations_total",
8895
+ {
8896
+ description: "Total number of streaming generations"
8897
+ }
8898
+ ),
8899
+ streamingDeltasEmittedCounter: meter.createCounter(
8900
+ "ax_gen_streaming_deltas_emitted_total",
8901
+ {
8902
+ description: "Total number of streaming deltas emitted"
8903
+ }
8904
+ ),
8905
+ streamingFinalizationLatencyHistogram: meter.createHistogram(
8906
+ "ax_gen_streaming_finalization_duration_ms",
8907
+ {
8908
+ description: "Duration of streaming response finalization",
8909
+ unit: "ms"
8910
+ }
8911
+ ),
8912
+ // Memory and samples metrics
8913
+ samplesGeneratedHistogram: meter.createHistogram(
8914
+ "ax_gen_samples_generated",
8915
+ {
8916
+ description: "Number of samples generated per request"
8917
+ }
8918
+ ),
8919
+ resultPickerUsageCounter: meter.createCounter(
8920
+ "ax_gen_result_picker_usage_total",
8921
+ {
8922
+ description: "Total number of times result picker was used"
8923
+ }
8924
+ ),
8925
+ resultPickerLatencyHistogram: meter.createHistogram(
8926
+ "ax_gen_result_picker_duration_ms",
8927
+ {
8928
+ description: "Duration of result picker execution",
8929
+ unit: "ms"
8930
+ }
8931
+ ),
8932
+ // Signature complexity metrics
8933
+ inputFieldsGauge: meter.createGauge("ax_gen_input_fields", {
8934
+ description: "Number of input fields in signature"
8935
+ }),
8936
+ outputFieldsGauge: meter.createGauge("ax_gen_output_fields", {
8937
+ description: "Number of output fields in signature"
8938
+ }),
8939
+ examplesUsedGauge: meter.createGauge("ax_gen_examples_used", {
8940
+ description: "Number of examples used in generation"
8941
+ }),
8942
+ demosUsedGauge: meter.createGauge("ax_gen_demos_used", {
8943
+ description: "Number of demos used in generation"
8944
+ }),
8945
+ // Performance metrics
8946
+ promptRenderLatencyHistogram: meter.createHistogram(
8947
+ "ax_gen_prompt_render_duration_ms",
8948
+ {
8949
+ description: "Duration of prompt template rendering",
8950
+ unit: "ms"
8951
+ }
8952
+ ),
8953
+ extractionLatencyHistogram: meter.createHistogram(
8954
+ "ax_gen_extraction_duration_ms",
8955
+ {
8956
+ description: "Duration of value extraction from responses",
8957
+ unit: "ms"
8958
+ }
8959
+ ),
8960
+ assertionLatencyHistogram: meter.createHistogram(
8961
+ "ax_gen_assertion_duration_ms",
8962
+ {
8963
+ description: "Duration of assertion checking",
8964
+ unit: "ms"
8965
+ }
8966
+ ),
8967
+ // State management
8968
+ stateCreationLatencyHistogram: meter.createHistogram(
8969
+ "ax_gen_state_creation_duration_ms",
8970
+ {
8971
+ description: "Duration of state creation for multiple samples",
8972
+ unit: "ms"
8973
+ }
8974
+ ),
8975
+ memoryUpdateLatencyHistogram: meter.createHistogram(
8976
+ "ax_gen_memory_update_duration_ms",
8977
+ {
8978
+ description: "Duration of memory updates during generation",
8979
+ unit: "ms"
8980
+ }
8981
+ )
8982
+ };
8983
+ };
8984
+ var currentMetricsConfig = axDefaultMetricsConfig;
8985
+ var axUpdateMetricsConfig = (config) => {
8986
+ currentMetricsConfig = { ...currentMetricsConfig, ...config };
8987
+ };
8988
+ var axGetMetricsConfig = () => {
8989
+ return { ...currentMetricsConfig };
8990
+ };
8991
+ var sanitizeLabels2 = (labels) => {
8992
+ const sanitized = {};
8993
+ for (const [key, value] of Object.entries(labels)) {
8994
+ if (value !== void 0 && value !== null) {
8995
+ const stringValue = String(value);
8996
+ const maxLength = currentMetricsConfig.maxLabelLength;
8997
+ sanitized[key] = stringValue.length > maxLength ? stringValue.substring(0, maxLength) : stringValue;
8998
+ }
8999
+ }
9000
+ return sanitized;
9001
+ };
9002
+ var recordGenerationMetric = (instruments, duration, success, signatureName, aiService, model) => {
9003
+ try {
9004
+ const labels = sanitizeLabels2({
9005
+ success: success.toString(),
9006
+ ...signatureName ? { signature: signatureName } : {},
9007
+ ...aiService ? { ai_service: aiService } : {},
9008
+ ...model ? { model } : {}
9009
+ });
9010
+ if (instruments.generationLatencyHistogram) {
9011
+ instruments.generationLatencyHistogram.record(duration, labels);
9012
+ }
9013
+ if (instruments.generationRequestsCounter) {
9014
+ instruments.generationRequestsCounter.add(1, labels);
9015
+ }
9016
+ if (!success && instruments.generationErrorsCounter) {
9017
+ instruments.generationErrorsCounter.add(1, labels);
9018
+ }
9019
+ } catch (error) {
9020
+ console.warn("Failed to record generation metric:", error);
9021
+ }
9022
+ };
9023
+ var recordMultiStepMetric = (instruments, stepsUsed, maxSteps, signatureName) => {
9024
+ try {
9025
+ const labels = sanitizeLabels2({
9026
+ ...signatureName ? { signature: signatureName } : {}
9027
+ });
9028
+ if (stepsUsed > 1 && instruments.multiStepGenerationsCounter) {
9029
+ instruments.multiStepGenerationsCounter.add(1, labels);
9030
+ }
9031
+ if (instruments.stepsPerGenerationHistogram) {
9032
+ instruments.stepsPerGenerationHistogram.record(stepsUsed, labels);
9033
+ }
9034
+ if (stepsUsed >= maxSteps && instruments.maxStepsReachedCounter) {
9035
+ instruments.maxStepsReachedCounter.add(1, labels);
9036
+ }
9037
+ } catch (error) {
9038
+ console.warn("Failed to record multi-step metric:", error);
9039
+ }
9040
+ };
9041
+ var recordValidationErrorMetric = (instruments, errorType, signatureName) => {
9042
+ try {
9043
+ const labels = sanitizeLabels2({
9044
+ error_type: errorType,
9045
+ ...signatureName ? { signature: signatureName } : {}
9046
+ });
9047
+ if (errorType === "validation" && instruments.validationErrorsCounter) {
9048
+ instruments.validationErrorsCounter.add(1, labels);
9049
+ }
9050
+ if (errorType === "assertion" && instruments.assertionErrorsCounter) {
9051
+ instruments.assertionErrorsCounter.add(1, labels);
9052
+ }
9053
+ } catch (error) {
9054
+ console.warn("Failed to record validation error metric:", error);
9055
+ }
9056
+ };
9057
+ var recordErrorCorrectionMetric = (instruments, attempts, success, maxRetries, signatureName) => {
9058
+ try {
9059
+ const labels = sanitizeLabels2({
9060
+ success: success.toString(),
9061
+ ...signatureName ? { signature: signatureName } : {}
9062
+ });
9063
+ if (instruments.errorCorrectionAttemptsHistogram) {
9064
+ instruments.errorCorrectionAttemptsHistogram.record(attempts, labels);
9065
+ }
9066
+ if (success && instruments.errorCorrectionSuccessCounter) {
9067
+ instruments.errorCorrectionSuccessCounter.add(1, labels);
9068
+ }
9069
+ if (!success) {
9070
+ if (instruments.errorCorrectionFailureCounter) {
9071
+ instruments.errorCorrectionFailureCounter.add(1, labels);
9072
+ }
9073
+ if (attempts >= maxRetries && instruments.maxRetriesReachedCounter) {
9074
+ instruments.maxRetriesReachedCounter.add(1, labels);
9075
+ }
9076
+ }
9077
+ } catch (error) {
9078
+ console.warn("Failed to record error correction metric:", error);
9079
+ }
9080
+ };
9081
+ var recordFunctionCallingMetric = (instruments, functionsEnabled, functionsExecuted, hadFunctionCalls, functionErrorCorrection = false, signatureName) => {
9082
+ try {
9083
+ const labels = sanitizeLabels2({
9084
+ functions_enabled: functionsEnabled.toString(),
9085
+ had_function_calls: hadFunctionCalls.toString(),
9086
+ ...signatureName ? { signature: signatureName } : {}
9087
+ });
9088
+ if (functionsEnabled && instruments.functionsEnabledGenerationsCounter) {
9089
+ instruments.functionsEnabledGenerationsCounter.add(1, labels);
9090
+ }
9091
+ if (hadFunctionCalls && instruments.functionCallStepsCounter) {
9092
+ instruments.functionCallStepsCounter.add(1, labels);
9093
+ }
9094
+ if (functionsExecuted > 0 && instruments.functionsExecutedPerGenerationHistogram) {
9095
+ instruments.functionsExecutedPerGenerationHistogram.record(
9096
+ functionsExecuted,
9097
+ labels
9098
+ );
9099
+ }
9100
+ if (functionErrorCorrection && instruments.functionErrorCorrectionCounter) {
9101
+ instruments.functionErrorCorrectionCounter.add(1, labels);
9102
+ }
9103
+ } catch (error) {
9104
+ console.warn("Failed to record function calling metric:", error);
9105
+ }
9106
+ };
9107
+ var recordFieldProcessingMetric = (instruments, fieldProcessorsExecuted, streamingFieldProcessorsExecuted, signatureName) => {
9108
+ try {
9109
+ const labels = sanitizeLabels2({
9110
+ ...signatureName ? { signature: signatureName } : {}
9111
+ });
9112
+ if (fieldProcessorsExecuted > 0 && instruments.fieldProcessorsExecutedCounter) {
9113
+ instruments.fieldProcessorsExecutedCounter.add(
9114
+ fieldProcessorsExecuted,
9115
+ labels
9116
+ );
9117
+ }
9118
+ if (streamingFieldProcessorsExecuted > 0 && instruments.streamingFieldProcessorsExecutedCounter) {
9119
+ instruments.streamingFieldProcessorsExecutedCounter.add(
9120
+ streamingFieldProcessorsExecuted,
9121
+ labels
9122
+ );
9123
+ }
9124
+ } catch (error) {
9125
+ console.warn("Failed to record field processing metric:", error);
9126
+ }
9127
+ };
9128
+ var recordStreamingMetric = (instruments, isStreaming, deltasEmitted, finalizationDuration, signatureName) => {
9129
+ try {
9130
+ const labels = sanitizeLabels2({
9131
+ is_streaming: isStreaming.toString(),
9132
+ ...signatureName ? { signature: signatureName } : {}
9133
+ });
9134
+ if (isStreaming && instruments.streamingGenerationsCounter) {
9135
+ instruments.streamingGenerationsCounter.add(1, labels);
9136
+ }
9137
+ if (deltasEmitted > 0 && instruments.streamingDeltasEmittedCounter) {
9138
+ instruments.streamingDeltasEmittedCounter.add(deltasEmitted, labels);
9139
+ }
9140
+ if (finalizationDuration && instruments.streamingFinalizationLatencyHistogram) {
9141
+ instruments.streamingFinalizationLatencyHistogram.record(
9142
+ finalizationDuration,
9143
+ labels
9144
+ );
9145
+ }
9146
+ } catch (error) {
9147
+ console.warn("Failed to record streaming metric:", error);
9148
+ }
9149
+ };
9150
+ var recordSamplesMetric = (instruments, samplesCount, resultPickerUsed, resultPickerLatency, signatureName) => {
9151
+ try {
9152
+ const labels = sanitizeLabels2({
9153
+ result_picker_used: resultPickerUsed.toString(),
9154
+ ...signatureName ? { signature: signatureName } : {}
9155
+ });
9156
+ if (instruments.samplesGeneratedHistogram) {
9157
+ instruments.samplesGeneratedHistogram.record(samplesCount, labels);
9158
+ }
9159
+ if (resultPickerUsed && instruments.resultPickerUsageCounter) {
9160
+ instruments.resultPickerUsageCounter.add(1, labels);
9161
+ }
9162
+ if (resultPickerLatency && instruments.resultPickerLatencyHistogram) {
9163
+ instruments.resultPickerLatencyHistogram.record(
9164
+ resultPickerLatency,
9165
+ labels
9166
+ );
9167
+ }
9168
+ } catch (error) {
9169
+ console.warn("Failed to record samples metric:", error);
9170
+ }
9171
+ };
9172
+ var recordSignatureComplexityMetrics = (instruments, inputFields, outputFields, examplesCount, demosCount, signatureName) => {
9173
+ try {
9174
+ const labels = sanitizeLabels2({
9175
+ ...signatureName ? { signature: signatureName } : {}
9176
+ });
9177
+ if (instruments.inputFieldsGauge) {
9178
+ instruments.inputFieldsGauge.record(inputFields, labels);
9179
+ }
9180
+ if (instruments.outputFieldsGauge) {
9181
+ instruments.outputFieldsGauge.record(outputFields, labels);
9182
+ }
9183
+ if (instruments.examplesUsedGauge) {
9184
+ instruments.examplesUsedGauge.record(examplesCount, labels);
9185
+ }
9186
+ if (instruments.demosUsedGauge) {
9187
+ instruments.demosUsedGauge.record(demosCount, labels);
9188
+ }
9189
+ } catch (error) {
9190
+ console.warn("Failed to record signature complexity metrics:", error);
9191
+ }
9192
+ };
9193
+ var recordPerformanceMetric = (instruments, metricType, duration, signatureName) => {
9194
+ try {
9195
+ const labels = sanitizeLabels2({
9196
+ metric_type: metricType,
9197
+ ...signatureName ? { signature: signatureName } : {}
9198
+ });
9199
+ switch (metricType) {
9200
+ case "prompt_render":
9201
+ if (instruments.promptRenderLatencyHistogram) {
9202
+ instruments.promptRenderLatencyHistogram.record(duration, labels);
9203
+ }
9204
+ break;
9205
+ case "extraction":
9206
+ if (instruments.extractionLatencyHistogram) {
9207
+ instruments.extractionLatencyHistogram.record(duration, labels);
9208
+ }
9209
+ break;
9210
+ case "assertion":
9211
+ if (instruments.assertionLatencyHistogram) {
9212
+ instruments.assertionLatencyHistogram.record(duration, labels);
9213
+ }
9214
+ break;
9215
+ case "state_creation":
9216
+ if (instruments.stateCreationLatencyHistogram) {
9217
+ instruments.stateCreationLatencyHistogram.record(duration, labels);
9218
+ }
9219
+ break;
9220
+ case "memory_update":
9221
+ if (instruments.memoryUpdateLatencyHistogram) {
9222
+ instruments.memoryUpdateLatencyHistogram.record(duration, labels);
9223
+ }
9224
+ break;
9225
+ }
9226
+ } catch (error) {
9227
+ console.warn("Failed to record performance metric:", error);
9228
+ }
9229
+ };
9230
+
9231
+ // dsp/processResponse.ts
9232
+ var import_web5 = require("stream/web");
9233
+
9234
+ // ai/util.ts
9235
+ function mergeFunctionCalls(functionCalls, functionCallDeltas) {
9236
+ for (const _fc of functionCallDeltas) {
9237
+ const fc = functionCalls.find((fc2) => fc2.id === _fc.id);
9238
+ if (fc) {
9239
+ if (typeof _fc.function.name == "string" && _fc.function.name.length > 0) {
9240
+ fc.function.name += _fc.function.name;
9241
+ }
9242
+ if (typeof _fc.function.params == "string" && _fc.function.params.length > 0) {
9243
+ fc.function.params += _fc.function.params;
9244
+ }
9245
+ if (typeof _fc.function.params == "object") {
9246
+ fc.function.params = _fc.function.params;
9247
+ }
9248
+ } else {
9249
+ functionCalls.push(_fc);
9250
+ }
9251
+ }
9252
+ }
9253
+
9254
+ // dsp/sig.ts
9255
+ var import_crypto3 = require("crypto");
9256
+
9257
+ // dsp/parser.ts
9258
+ var SignatureValidationError = class extends Error {
9259
+ constructor(message, position, context3, suggestion) {
9260
+ super(message);
9261
+ this.position = position;
9262
+ this.context = context3;
9263
+ this.suggestion = suggestion;
9264
+ this.name = "SignatureValidationError";
9265
+ }
9266
+ };
9267
+ var SignatureParser = class {
9268
+ input;
9269
+ position;
9270
+ currentFieldName = null;
9271
+ currentSection = "description";
9272
+ constructor(input) {
9273
+ this.input = input.trim();
9274
+ this.position = 0;
9275
+ if (!this.input) {
9276
+ throw new SignatureValidationError(
9277
+ "Empty signature provided",
9278
+ 0,
9279
+ "",
9280
+ 'A signature must contain at least input and output fields separated by "->". Example: "userQuery:string -> aiResponse:string"'
9281
+ );
9282
+ }
9283
+ }
9284
+ parse() {
9285
+ try {
9286
+ this.skipWhitespace();
9287
+ const optionalDesc = this.parseParsedString();
9288
+ this.skipWhitespace();
9289
+ this.currentSection = "inputs";
9290
+ const inputs = this.parseFieldList(
9291
+ this.parseInputField.bind(this),
9292
+ "input"
9293
+ );
9294
+ this.skipWhitespace();
9295
+ if (this.position >= this.input.length) {
9296
+ throw new SignatureValidationError(
9297
+ "Incomplete signature: Missing output section",
9298
+ this.position,
9299
+ this.getErrorContext(),
9300
+ 'Add "->" followed by output fields. Example: "-> responseText:string"'
9301
+ );
9302
+ }
9303
+ this.expectArrow();
9304
+ this.skipWhitespace();
9305
+ if (this.position >= this.input.length) {
9306
+ throw new SignatureValidationError(
8121
9307
  'Incomplete signature: No output fields specified after "->"',
8122
9308
  this.position,
8123
9309
  this.getErrorContext(),
@@ -10434,6 +11620,15 @@ var AxGen = class extends AxProgramWithSignature {
10434
11620
  this.functions = parseFunctions(options.functions);
10435
11621
  }
10436
11622
  }
11623
+ getSignatureName() {
11624
+ return this.signature.getDescription() || "unknown_signature";
11625
+ }
11626
+ getMetricsInstruments() {
11627
+ return getOrCreateGenMetricsInstruments();
11628
+ }
11629
+ updateMeter(meter) {
11630
+ getOrCreateGenMetricsInstruments(meter);
11631
+ }
10437
11632
  createStates(n) {
10438
11633
  return Array.from({ length: n }, (_, index) => ({
10439
11634
  index,
@@ -10623,6 +11818,7 @@ var AxGen = class extends AxProgramWithSignature {
10623
11818
  );
10624
11819
  }
10625
11820
  let prompt;
11821
+ const promptRenderStart = performance.now();
10626
11822
  if (Array.isArray(values)) {
10627
11823
  validateAxMessageArray(values);
10628
11824
  prompt = this.promptTemplate.render(values, {
@@ -10636,7 +11832,27 @@ var AxGen = class extends AxProgramWithSignature {
10636
11832
  demos: this.demos
10637
11833
  });
10638
11834
  }
11835
+ const promptRenderDuration = performance.now() - promptRenderStart;
11836
+ const metricsInstruments = this.getMetricsInstruments();
11837
+ if (metricsInstruments) {
11838
+ recordPerformanceMetric(
11839
+ metricsInstruments,
11840
+ "prompt_render",
11841
+ promptRenderDuration,
11842
+ this.getSignatureName()
11843
+ );
11844
+ }
11845
+ const memoryUpdateStart = performance.now();
10639
11846
  mem.addRequest(prompt, options.sessionId);
11847
+ const memoryUpdateDuration = performance.now() - memoryUpdateStart;
11848
+ if (metricsInstruments) {
11849
+ recordPerformanceMetric(
11850
+ metricsInstruments,
11851
+ "memory_update",
11852
+ memoryUpdateDuration,
11853
+ this.getSignatureName()
11854
+ );
11855
+ }
10640
11856
  multiStepLoop: for (let n = 0; n < maxSteps; n++) {
10641
11857
  const firstStep = n === 0;
10642
11858
  for (let errCount = 0; errCount < maxRetries; errCount++) {
@@ -10665,8 +11881,48 @@ var AxGen = class extends AxProgramWithSignature {
10665
11881
  options?.sessionId
10666
11882
  );
10667
11883
  if (shouldContinue) {
11884
+ const metricsInstruments4 = this.getMetricsInstruments();
11885
+ if (metricsInstruments4) {
11886
+ recordMultiStepMetric(
11887
+ metricsInstruments4,
11888
+ n + 1,
11889
+ maxSteps,
11890
+ this.getSignatureName()
11891
+ );
11892
+ }
10668
11893
  continue multiStepLoop;
10669
11894
  }
11895
+ const metricsInstruments3 = this.getMetricsInstruments();
11896
+ if (metricsInstruments3) {
11897
+ recordMultiStepMetric(
11898
+ metricsInstruments3,
11899
+ n + 1,
11900
+ maxSteps,
11901
+ this.getSignatureName()
11902
+ );
11903
+ const allFunctionsExecuted = /* @__PURE__ */ new Set();
11904
+ states.forEach((state) => {
11905
+ state.functionsExecuted.forEach(
11906
+ (func) => allFunctionsExecuted.add(func)
11907
+ );
11908
+ });
11909
+ if (allFunctionsExecuted.size > 0) {
11910
+ recordFunctionCallingMetric(
11911
+ metricsInstruments3,
11912
+ true,
11913
+ allFunctionsExecuted.size,
11914
+ true,
11915
+ false,
11916
+ this.getSignatureName()
11917
+ );
11918
+ }
11919
+ recordFieldProcessingMetric(
11920
+ metricsInstruments3,
11921
+ this.fieldProcessors.length,
11922
+ this.streamingFieldProcessors.length,
11923
+ this.getSignatureName()
11924
+ );
11925
+ }
10670
11926
  this.getLogger(ai, options)?.("", { tags: ["responseEnd"] });
10671
11927
  return;
10672
11928
  } catch (e) {
@@ -10675,6 +11931,14 @@ var AxGen = class extends AxProgramWithSignature {
10675
11931
  if (e instanceof ValidationError) {
10676
11932
  errorFields = e.getFixingInstructions();
10677
11933
  err = e;
11934
+ const metricsInstruments3 = this.getMetricsInstruments();
11935
+ if (metricsInstruments3) {
11936
+ recordValidationErrorMetric(
11937
+ metricsInstruments3,
11938
+ "validation",
11939
+ this.getSignatureName()
11940
+ );
11941
+ }
10678
11942
  if (span) {
10679
11943
  span.addEvent("validation.error", {
10680
11944
  message: e.toString(),
@@ -10685,6 +11949,14 @@ var AxGen = class extends AxProgramWithSignature {
10685
11949
  const e1 = e;
10686
11950
  errorFields = e1.getFixingInstructions();
10687
11951
  err = e;
11952
+ const assertionMetricsInstruments = this.getMetricsInstruments();
11953
+ if (assertionMetricsInstruments) {
11954
+ recordValidationErrorMetric(
11955
+ assertionMetricsInstruments,
11956
+ "assertion",
11957
+ this.getSignatureName()
11958
+ );
11959
+ }
10688
11960
  if (span) {
10689
11961
  span.addEvent("assertion.error", {
10690
11962
  message: e1.toString(),
@@ -10706,12 +11978,31 @@ var AxGen = class extends AxProgramWithSignature {
10706
11978
  }
10707
11979
  }
10708
11980
  }
11981
+ const metricsInstruments2 = this.getMetricsInstruments();
11982
+ if (metricsInstruments2) {
11983
+ recordErrorCorrectionMetric(
11984
+ metricsInstruments2,
11985
+ maxRetries,
11986
+ false,
11987
+ // failed
11988
+ maxRetries,
11989
+ this.getSignatureName()
11990
+ );
11991
+ }
10709
11992
  throw enhanceError(
10710
11993
  new Error(`Unable to fix validation error: ${err?.toString()}`),
10711
11994
  ai,
10712
11995
  this.signature
10713
11996
  );
10714
11997
  }
11998
+ if (metricsInstruments) {
11999
+ recordMultiStepMetric(
12000
+ metricsInstruments,
12001
+ maxSteps,
12002
+ maxSteps,
12003
+ this.getSignatureName()
12004
+ );
12005
+ }
10715
12006
  throw enhanceError(
10716
12007
  new Error(`Max steps reached: ${maxSteps}`),
10717
12008
  ai,
@@ -10719,7 +12010,18 @@ var AxGen = class extends AxProgramWithSignature {
10719
12010
  );
10720
12011
  }
10721
12012
  async *_forward1(ai, values, options) {
12013
+ const stateCreationStart = performance.now();
10722
12014
  const states = this.createStates(options.sampleCount ?? 1);
12015
+ const stateCreationDuration = performance.now() - stateCreationStart;
12016
+ const metricsInstruments = this.getMetricsInstruments();
12017
+ if (metricsInstruments) {
12018
+ recordPerformanceMetric(
12019
+ metricsInstruments,
12020
+ "state_creation",
12021
+ stateCreationDuration,
12022
+ this.getSignatureName()
12023
+ );
12024
+ }
10723
12025
  const tracer = options?.tracer ?? this.options?.tracer ?? ai.getOptions().tracer;
10724
12026
  let functions = this.functions;
10725
12027
  if (options?.functions) {
@@ -10778,29 +12080,111 @@ var AxGen = class extends AxProgramWithSignature {
10778
12080
  }
10779
12081
  }
10780
12082
  async forward(ai, values, options) {
10781
- const generator = this._forward1(ai, values, options ?? {});
10782
- let buffer = [];
10783
- let currentVersion = 0;
10784
- for await (const delta of generator) {
10785
- if (delta.version !== currentVersion) {
10786
- buffer = [];
12083
+ const startTime = performance.now();
12084
+ const signatureName = this.getSignatureName();
12085
+ const isStreaming = options?.stream ?? false;
12086
+ let success = false;
12087
+ let errorCorrectionAttempts = 0;
12088
+ let functionsEnabled = false;
12089
+ let functionsExecuted = 0;
12090
+ let resultPickerUsed = false;
12091
+ try {
12092
+ const metricsInstruments = this.getMetricsInstruments();
12093
+ if (metricsInstruments) {
12094
+ recordSignatureComplexityMetrics(
12095
+ metricsInstruments,
12096
+ this.signature.getInputFields().length,
12097
+ this.signature.getOutputFields().length,
12098
+ this.examples?.length ?? 0,
12099
+ this.demos?.length ?? 0,
12100
+ signatureName
12101
+ );
12102
+ }
12103
+ functionsEnabled = !!(options?.functions || this.functions);
12104
+ const generator = this._forward1(ai, values, options ?? {});
12105
+ let buffer = [];
12106
+ let currentVersion = 0;
12107
+ let deltasEmitted = 0;
12108
+ for await (const delta of generator) {
12109
+ if (delta.version !== currentVersion) {
12110
+ buffer = [];
12111
+ }
12112
+ currentVersion = delta.version;
12113
+ buffer = mergeDeltas(buffer, delta);
12114
+ deltasEmitted++;
12115
+ }
12116
+ errorCorrectionAttempts = currentVersion;
12117
+ const resultPickerStart = performance.now();
12118
+ resultPickerUsed = !!options?.resultPicker;
12119
+ const selectedIndex = await selectFromSamples(
12120
+ buffer,
12121
+ {
12122
+ resultPicker: options?.resultPicker
12123
+ },
12124
+ // Pass memory to enable function result selection
12125
+ options?.mem,
12126
+ options?.sessionId
12127
+ );
12128
+ const resultPickerLatency = performance.now() - resultPickerStart;
12129
+ const selectedResult = buffer[selectedIndex];
12130
+ const result = selectedResult?.delta ?? {};
12131
+ this.trace = { ...values, ...result };
12132
+ success = true;
12133
+ if (metricsInstruments) {
12134
+ recordSamplesMetric(
12135
+ metricsInstruments,
12136
+ buffer.length,
12137
+ resultPickerUsed,
12138
+ resultPickerUsed ? resultPickerLatency : void 0,
12139
+ signatureName
12140
+ );
12141
+ recordStreamingMetric(
12142
+ metricsInstruments,
12143
+ isStreaming,
12144
+ deltasEmitted,
12145
+ void 0,
12146
+ // finalization latency not applicable here
12147
+ signatureName
12148
+ );
12149
+ }
12150
+ return result;
12151
+ } catch (error) {
12152
+ success = false;
12153
+ throw error;
12154
+ } finally {
12155
+ const duration = performance.now() - startTime;
12156
+ const finalMetricsInstruments = this.getMetricsInstruments();
12157
+ if (finalMetricsInstruments) {
12158
+ recordGenerationMetric(
12159
+ finalMetricsInstruments,
12160
+ duration,
12161
+ success,
12162
+ signatureName,
12163
+ ai.getName(),
12164
+ options?.model
12165
+ );
12166
+ if (functionsEnabled) {
12167
+ recordFunctionCallingMetric(
12168
+ finalMetricsInstruments,
12169
+ functionsEnabled,
12170
+ functionsExecuted,
12171
+ functionsExecuted > 0,
12172
+ false,
12173
+ // function error correction tracking would need more complex logic
12174
+ signatureName
12175
+ );
12176
+ }
12177
+ if (errorCorrectionAttempts > 0) {
12178
+ recordErrorCorrectionMetric(
12179
+ finalMetricsInstruments,
12180
+ errorCorrectionAttempts,
12181
+ success,
12182
+ options?.maxRetries ?? 10,
12183
+ signatureName
12184
+ );
12185
+ }
10787
12186
  }
10788
- currentVersion = delta.version;
10789
- buffer = mergeDeltas(buffer, delta);
10790
12187
  }
10791
- const selectedIndex = await selectFromSamples(
10792
- buffer,
10793
- {
10794
- resultPicker: options?.resultPicker
10795
- },
10796
- // Pass memory to enable function result selection
10797
- options?.mem,
10798
- options?.sessionId
10799
- );
10800
- const selectedResult = buffer[selectedIndex];
10801
- const result = selectedResult?.delta ?? {};
10802
- this.trace = { ...values, ...result };
10803
- return result;
10804
12188
  }
10805
12189
  async *streamingForward(ai, values, options) {
10806
12190
  if (!options?.resultPicker) {
@@ -11493,6 +12877,466 @@ function validateModels2(services) {
11493
12877
  }
11494
12878
 
11495
12879
  // dsp/optimizer.ts
12880
+ var axDefaultOptimizerMetricsConfig = {
12881
+ enabled: true,
12882
+ enabledCategories: [
12883
+ "optimization",
12884
+ "convergence",
12885
+ "resource_usage",
12886
+ "teacher_student",
12887
+ "checkpointing",
12888
+ "pareto"
12889
+ ],
12890
+ maxLabelLength: 100,
12891
+ samplingRate: 1
12892
+ };
12893
+ var globalOptimizerMetricsInstruments;
12894
+ var getOrCreateOptimizerMetricsInstruments = (meter) => {
12895
+ if (globalOptimizerMetricsInstruments) {
12896
+ return globalOptimizerMetricsInstruments;
12897
+ }
12898
+ if (meter) {
12899
+ globalOptimizerMetricsInstruments = createOptimizerMetricsInstruments(meter);
12900
+ return globalOptimizerMetricsInstruments;
12901
+ }
12902
+ return void 0;
12903
+ };
12904
+ var currentOptimizerMetricsConfig = axDefaultOptimizerMetricsConfig;
12905
+ var axUpdateOptimizerMetricsConfig = (config) => {
12906
+ currentOptimizerMetricsConfig = {
12907
+ ...currentOptimizerMetricsConfig,
12908
+ ...config
12909
+ };
12910
+ };
12911
+ var axGetOptimizerMetricsConfig = () => {
12912
+ return { ...currentOptimizerMetricsConfig };
12913
+ };
12914
+ var createOptimizerMetricsInstruments = (meter) => {
12915
+ return {
12916
+ // Optimization flow metrics
12917
+ optimizationLatencyHistogram: meter.createHistogram(
12918
+ "ax_optimizer_optimization_duration_ms",
12919
+ {
12920
+ description: "End-to-end duration of optimization runs",
12921
+ unit: "ms"
12922
+ }
12923
+ ),
12924
+ optimizationRequestsCounter: meter.createCounter(
12925
+ "ax_optimizer_optimization_requests_total",
12926
+ {
12927
+ description: "Total number of optimization requests"
12928
+ }
12929
+ ),
12930
+ optimizationErrorsCounter: meter.createCounter(
12931
+ "ax_optimizer_optimization_errors_total",
12932
+ {
12933
+ description: "Total number of failed optimizations"
12934
+ }
12935
+ ),
12936
+ // Convergence metrics
12937
+ convergenceRoundsHistogram: meter.createHistogram(
12938
+ "ax_optimizer_convergence_rounds",
12939
+ {
12940
+ description: "Number of rounds until convergence"
12941
+ }
12942
+ ),
12943
+ convergenceScoreGauge: meter.createGauge("ax_optimizer_convergence_score", {
12944
+ description: "Current best score during optimization"
12945
+ }),
12946
+ convergenceImprovementGauge: meter.createGauge(
12947
+ "ax_optimizer_convergence_improvement",
12948
+ {
12949
+ description: "Improvement in score from baseline"
12950
+ }
12951
+ ),
12952
+ stagnationRoundsGauge: meter.createGauge("ax_optimizer_stagnation_rounds", {
12953
+ description: "Number of rounds without improvement"
12954
+ }),
12955
+ earlyStoppingCounter: meter.createCounter(
12956
+ "ax_optimizer_early_stopping_total",
12957
+ {
12958
+ description: "Total number of early stopping events"
12959
+ }
12960
+ ),
12961
+ // Resource usage metrics
12962
+ tokenUsageCounter: meter.createCounter("ax_optimizer_token_usage_total", {
12963
+ description: "Total tokens used during optimization"
12964
+ }),
12965
+ costUsageCounter: meter.createCounter("ax_optimizer_cost_usage_total", {
12966
+ description: "Total cost incurred during optimization",
12967
+ unit: "$"
12968
+ }),
12969
+ memoryUsageGauge: meter.createGauge("ax_optimizer_memory_usage_bytes", {
12970
+ description: "Peak memory usage during optimization",
12971
+ unit: "By"
12972
+ }),
12973
+ optimizationDurationHistogram: meter.createHistogram(
12974
+ "ax_optimizer_duration_ms",
12975
+ {
12976
+ description: "Duration of optimization runs",
12977
+ unit: "ms"
12978
+ }
12979
+ ),
12980
+ // Teacher-student metrics
12981
+ teacherStudentUsageCounter: meter.createCounter(
12982
+ "ax_optimizer_teacher_student_usage_total",
12983
+ {
12984
+ description: "Total number of teacher-student interactions"
12985
+ }
12986
+ ),
12987
+ teacherStudentLatencyHistogram: meter.createHistogram(
12988
+ "ax_optimizer_teacher_student_latency_ms",
12989
+ {
12990
+ description: "Latency of teacher-student interactions",
12991
+ unit: "ms"
12992
+ }
12993
+ ),
12994
+ teacherStudentScoreImprovementGauge: meter.createGauge(
12995
+ "ax_optimizer_teacher_student_score_improvement",
12996
+ {
12997
+ description: "Score improvement from teacher-student interactions"
12998
+ }
12999
+ ),
13000
+ // Checkpointing metrics
13001
+ checkpointSaveCounter: meter.createCounter(
13002
+ "ax_optimizer_checkpoint_save_total",
13003
+ {
13004
+ description: "Total number of checkpoint saves"
13005
+ }
13006
+ ),
13007
+ checkpointLoadCounter: meter.createCounter(
13008
+ "ax_optimizer_checkpoint_load_total",
13009
+ {
13010
+ description: "Total number of checkpoint loads"
13011
+ }
13012
+ ),
13013
+ checkpointSaveLatencyHistogram: meter.createHistogram(
13014
+ "ax_optimizer_checkpoint_save_latency_ms",
13015
+ {
13016
+ description: "Latency of checkpoint save operations",
13017
+ unit: "ms"
13018
+ }
13019
+ ),
13020
+ checkpointLoadLatencyHistogram: meter.createHistogram(
13021
+ "ax_optimizer_checkpoint_load_latency_ms",
13022
+ {
13023
+ description: "Latency of checkpoint load operations",
13024
+ unit: "ms"
13025
+ }
13026
+ ),
13027
+ // Pareto optimization metrics
13028
+ paretoOptimizationsCounter: meter.createCounter(
13029
+ "ax_optimizer_pareto_optimizations_total",
13030
+ {
13031
+ description: "Total number of Pareto optimizations"
13032
+ }
13033
+ ),
13034
+ paretoFrontSizeHistogram: meter.createHistogram(
13035
+ "ax_optimizer_pareto_front_size",
13036
+ {
13037
+ description: "Size of Pareto frontier"
13038
+ }
13039
+ ),
13040
+ paretoHypervolumeGauge: meter.createGauge(
13041
+ "ax_optimizer_pareto_hypervolume",
13042
+ {
13043
+ description: "Hypervolume of Pareto frontier"
13044
+ }
13045
+ ),
13046
+ paretoSolutionsGeneratedHistogram: meter.createHistogram(
13047
+ "ax_optimizer_pareto_solutions_generated",
13048
+ {
13049
+ description: "Number of solutions generated for Pareto optimization"
13050
+ }
13051
+ ),
13052
+ // Program complexity metrics
13053
+ programInputFieldsGauge: meter.createGauge(
13054
+ "ax_optimizer_program_input_fields",
13055
+ {
13056
+ description: "Number of input fields in optimized program"
13057
+ }
13058
+ ),
13059
+ programOutputFieldsGauge: meter.createGauge(
13060
+ "ax_optimizer_program_output_fields",
13061
+ {
13062
+ description: "Number of output fields in optimized program"
13063
+ }
13064
+ ),
13065
+ examplesCountGauge: meter.createGauge("ax_optimizer_examples_count", {
13066
+ description: "Number of training examples used"
13067
+ }),
13068
+ validationSetSizeGauge: meter.createGauge(
13069
+ "ax_optimizer_validation_set_size",
13070
+ {
13071
+ description: "Size of validation set used"
13072
+ }
13073
+ ),
13074
+ // Performance metrics
13075
+ evaluationLatencyHistogram: meter.createHistogram(
13076
+ "ax_optimizer_evaluation_latency_ms",
13077
+ {
13078
+ description: "Latency of program evaluations",
13079
+ unit: "ms"
13080
+ }
13081
+ ),
13082
+ demoGenerationLatencyHistogram: meter.createHistogram(
13083
+ "ax_optimizer_demo_generation_latency_ms",
13084
+ {
13085
+ description: "Latency of demo generation",
13086
+ unit: "ms"
13087
+ }
13088
+ ),
13089
+ metricComputationLatencyHistogram: meter.createHistogram(
13090
+ "ax_optimizer_metric_computation_latency_ms",
13091
+ {
13092
+ description: "Latency of metric computation",
13093
+ unit: "ms"
13094
+ }
13095
+ ),
13096
+ // Configuration metrics
13097
+ optimizerTypeGauge: meter.createGauge("ax_optimizer_type", {
13098
+ description: "Type of optimizer being used"
13099
+ }),
13100
+ targetScoreGauge: meter.createGauge("ax_optimizer_target_score", {
13101
+ description: "Target score for optimization"
13102
+ }),
13103
+ maxRoundsGauge: meter.createGauge("ax_optimizer_max_rounds", {
13104
+ description: "Maximum rounds for optimization"
13105
+ })
13106
+ };
13107
+ };
13108
+ var sanitizeOptimizerLabels = (labels) => {
13109
+ const sanitized = {};
13110
+ for (const [key, value] of Object.entries(labels)) {
13111
+ if (value !== void 0 && value !== null) {
13112
+ const stringValue = String(value);
13113
+ const maxLength = currentOptimizerMetricsConfig.maxLabelLength;
13114
+ sanitized[key] = stringValue.length > maxLength ? stringValue.substring(0, maxLength) : stringValue;
13115
+ }
13116
+ }
13117
+ return sanitized;
13118
+ };
13119
+ var recordOptimizationMetric = (instruments, duration, success, optimizerType, programSignature) => {
13120
+ try {
13121
+ const labels = sanitizeOptimizerLabels({
13122
+ success: success.toString(),
13123
+ optimizer_type: optimizerType,
13124
+ ...programSignature ? { program_signature: programSignature } : {}
13125
+ });
13126
+ if (instruments.optimizationLatencyHistogram) {
13127
+ instruments.optimizationLatencyHistogram.record(duration, labels);
13128
+ }
13129
+ if (instruments.optimizationRequestsCounter) {
13130
+ instruments.optimizationRequestsCounter.add(1, labels);
13131
+ }
13132
+ if (!success && instruments.optimizationErrorsCounter) {
13133
+ instruments.optimizationErrorsCounter.add(1, labels);
13134
+ }
13135
+ } catch (error) {
13136
+ console.warn("Failed to record optimization metric:", error);
13137
+ }
13138
+ };
13139
+ var recordConvergenceMetric = (instruments, rounds, currentScore, improvement, stagnationRounds, optimizerType) => {
13140
+ try {
13141
+ const labels = sanitizeOptimizerLabels({
13142
+ optimizer_type: optimizerType
13143
+ });
13144
+ if (instruments.convergenceRoundsHistogram) {
13145
+ instruments.convergenceRoundsHistogram.record(rounds, labels);
13146
+ }
13147
+ if (instruments.convergenceScoreGauge) {
13148
+ instruments.convergenceScoreGauge.record(currentScore, labels);
13149
+ }
13150
+ if (instruments.convergenceImprovementGauge) {
13151
+ instruments.convergenceImprovementGauge.record(improvement, labels);
13152
+ }
13153
+ if (instruments.stagnationRoundsGauge) {
13154
+ instruments.stagnationRoundsGauge.record(stagnationRounds, labels);
13155
+ }
13156
+ } catch (error) {
13157
+ console.warn("Failed to record convergence metric:", error);
13158
+ }
13159
+ };
13160
+ var recordEarlyStoppingMetric = (instruments, reason, optimizerType) => {
13161
+ try {
13162
+ const labels = sanitizeOptimizerLabels({
13163
+ reason,
13164
+ optimizer_type: optimizerType
13165
+ });
13166
+ if (instruments.earlyStoppingCounter) {
13167
+ instruments.earlyStoppingCounter.add(1, labels);
13168
+ }
13169
+ } catch (error) {
13170
+ console.warn("Failed to record early stopping metric:", error);
13171
+ }
13172
+ };
13173
+ var recordResourceUsageMetric = (instruments, tokensUsed, costIncurred, optimizerType, memoryUsage) => {
13174
+ try {
13175
+ const labels = sanitizeOptimizerLabels({
13176
+ optimizer_type: optimizerType
13177
+ });
13178
+ if (instruments.tokenUsageCounter) {
13179
+ instruments.tokenUsageCounter.add(tokensUsed, labels);
13180
+ }
13181
+ if (instruments.costUsageCounter) {
13182
+ instruments.costUsageCounter.add(costIncurred, labels);
13183
+ }
13184
+ if (memoryUsage !== void 0 && instruments.memoryUsageGauge) {
13185
+ instruments.memoryUsageGauge.record(memoryUsage, labels);
13186
+ }
13187
+ } catch (error) {
13188
+ console.warn("Failed to record resource usage metric:", error);
13189
+ }
13190
+ };
13191
+ var recordOptimizationDurationMetric = (instruments, duration, optimizerType) => {
13192
+ try {
13193
+ const labels = sanitizeOptimizerLabels({
13194
+ optimizer_type: optimizerType
13195
+ });
13196
+ if (instruments.optimizationDurationHistogram) {
13197
+ instruments.optimizationDurationHistogram.record(duration, labels);
13198
+ }
13199
+ } catch (error) {
13200
+ console.warn("Failed to record optimization duration metric:", error);
13201
+ }
13202
+ };
13203
+ var recordTeacherStudentMetric = (instruments, latency, scoreImprovement, optimizerType) => {
13204
+ try {
13205
+ const labels = sanitizeOptimizerLabels({
13206
+ optimizer_type: optimizerType
13207
+ });
13208
+ if (instruments.teacherStudentUsageCounter) {
13209
+ instruments.teacherStudentUsageCounter.add(1, labels);
13210
+ }
13211
+ if (instruments.teacherStudentLatencyHistogram) {
13212
+ instruments.teacherStudentLatencyHistogram.record(latency, labels);
13213
+ }
13214
+ if (instruments.teacherStudentScoreImprovementGauge) {
13215
+ instruments.teacherStudentScoreImprovementGauge.record(
13216
+ scoreImprovement,
13217
+ labels
13218
+ );
13219
+ }
13220
+ } catch (error) {
13221
+ console.warn("Failed to record teacher-student metric:", error);
13222
+ }
13223
+ };
13224
+ var recordCheckpointMetric = (instruments, operation, latency, success, optimizerType) => {
13225
+ try {
13226
+ const labels = sanitizeOptimizerLabels({
13227
+ operation,
13228
+ success: success.toString(),
13229
+ optimizer_type: optimizerType
13230
+ });
13231
+ if (operation === "save") {
13232
+ if (instruments.checkpointSaveCounter) {
13233
+ instruments.checkpointSaveCounter.add(1, labels);
13234
+ }
13235
+ if (instruments.checkpointSaveLatencyHistogram) {
13236
+ instruments.checkpointSaveLatencyHistogram.record(latency, labels);
13237
+ }
13238
+ } else {
13239
+ if (instruments.checkpointLoadCounter) {
13240
+ instruments.checkpointLoadCounter.add(1, labels);
13241
+ }
13242
+ if (instruments.checkpointLoadLatencyHistogram) {
13243
+ instruments.checkpointLoadLatencyHistogram.record(latency, labels);
13244
+ }
13245
+ }
13246
+ } catch (error) {
13247
+ console.warn("Failed to record checkpoint metric:", error);
13248
+ }
13249
+ };
13250
+ var recordParetoMetric = (instruments, frontSize, solutionsGenerated, optimizerType, hypervolume) => {
13251
+ try {
13252
+ const labels = sanitizeOptimizerLabels({
13253
+ optimizer_type: optimizerType
13254
+ });
13255
+ if (instruments.paretoOptimizationsCounter) {
13256
+ instruments.paretoOptimizationsCounter.add(1, labels);
13257
+ }
13258
+ if (instruments.paretoFrontSizeHistogram) {
13259
+ instruments.paretoFrontSizeHistogram.record(frontSize, labels);
13260
+ }
13261
+ if (hypervolume !== void 0 && instruments.paretoHypervolumeGauge) {
13262
+ instruments.paretoHypervolumeGauge.record(hypervolume, labels);
13263
+ }
13264
+ if (instruments.paretoSolutionsGeneratedHistogram) {
13265
+ instruments.paretoSolutionsGeneratedHistogram.record(
13266
+ solutionsGenerated,
13267
+ labels
13268
+ );
13269
+ }
13270
+ } catch (error) {
13271
+ console.warn("Failed to record Pareto metric:", error);
13272
+ }
13273
+ };
13274
+ var recordProgramComplexityMetric = (instruments, inputFields, outputFields, examplesCount, validationSetSize, optimizerType) => {
13275
+ try {
13276
+ const labels = sanitizeOptimizerLabels({
13277
+ optimizer_type: optimizerType
13278
+ });
13279
+ if (instruments.programInputFieldsGauge) {
13280
+ instruments.programInputFieldsGauge.record(inputFields, labels);
13281
+ }
13282
+ if (instruments.programOutputFieldsGauge) {
13283
+ instruments.programOutputFieldsGauge.record(outputFields, labels);
13284
+ }
13285
+ if (instruments.examplesCountGauge) {
13286
+ instruments.examplesCountGauge.record(examplesCount, labels);
13287
+ }
13288
+ if (instruments.validationSetSizeGauge) {
13289
+ instruments.validationSetSizeGauge.record(validationSetSize, labels);
13290
+ }
13291
+ } catch (error) {
13292
+ console.warn("Failed to record program complexity metric:", error);
13293
+ }
13294
+ };
13295
+ var recordOptimizerPerformanceMetric = (instruments, metricType, duration, optimizerType) => {
13296
+ try {
13297
+ const labels = sanitizeOptimizerLabels({
13298
+ metric_type: metricType,
13299
+ optimizer_type: optimizerType
13300
+ });
13301
+ switch (metricType) {
13302
+ case "evaluation":
13303
+ if (instruments.evaluationLatencyHistogram) {
13304
+ instruments.evaluationLatencyHistogram.record(duration, labels);
13305
+ }
13306
+ break;
13307
+ case "demo_generation":
13308
+ if (instruments.demoGenerationLatencyHistogram) {
13309
+ instruments.demoGenerationLatencyHistogram.record(duration, labels);
13310
+ }
13311
+ break;
13312
+ case "metric_computation":
13313
+ if (instruments.metricComputationLatencyHistogram) {
13314
+ instruments.metricComputationLatencyHistogram.record(duration, labels);
13315
+ }
13316
+ break;
13317
+ }
13318
+ } catch (error) {
13319
+ console.warn("Failed to record optimizer performance metric:", error);
13320
+ }
13321
+ };
13322
+ var recordOptimizerConfigurationMetric = (instruments, optimizerType, targetScore, maxRounds) => {
13323
+ try {
13324
+ const labels = sanitizeOptimizerLabels({
13325
+ optimizer_type: optimizerType
13326
+ });
13327
+ if (instruments.optimizerTypeGauge) {
13328
+ instruments.optimizerTypeGauge.record(1, labels);
13329
+ }
13330
+ if (targetScore !== void 0 && instruments.targetScoreGauge) {
13331
+ instruments.targetScoreGauge.record(targetScore, labels);
13332
+ }
13333
+ if (maxRounds !== void 0 && instruments.maxRoundsGauge) {
13334
+ instruments.maxRoundsGauge.record(maxRounds, labels);
13335
+ }
13336
+ } catch (error) {
13337
+ console.warn("Failed to record optimizer configuration metric:", error);
13338
+ }
13339
+ };
11496
13340
  var AxDefaultCostTracker = class {
11497
13341
  tokenUsage = {};
11498
13342
  totalTokens = 0;
@@ -11566,6 +13410,8 @@ var AxBaseOptimizer = class {
11566
13410
  configurationHistory = [];
11567
13411
  // Common optimization statistics
11568
13412
  stats;
13413
+ // Metrics instruments
13414
+ metricsInstruments;
11569
13415
  constructor(args) {
11570
13416
  if (args.examples.length === 0) {
11571
13417
  throw new Error("No examples found");
@@ -11589,6 +13435,9 @@ var AxBaseOptimizer = class {
11589
13435
  maxTokens: 1e6
11590
13436
  });
11591
13437
  this.costTracker = args.costTracker ?? costTracker;
13438
+ this.metricsInstruments = getOrCreateOptimizerMetricsInstruments(
13439
+ axGlobals.meter
13440
+ );
11592
13441
  this.stats = this.initializeStats();
11593
13442
  }
11594
13443
  /**
@@ -11660,6 +13509,7 @@ var AxBaseOptimizer = class {
11660
13509
  patienceExhausted: reason.includes("improvement"),
11661
13510
  reason
11662
13511
  };
13512
+ this.recordEarlyStoppingMetrics(reason, "unknown");
11663
13513
  if (this.onEarlyStop) {
11664
13514
  this.onEarlyStop(reason, this.stats);
11665
13515
  }
@@ -11803,6 +13653,12 @@ var AxBaseOptimizer = class {
11803
13653
  }
11804
13654
  this.updateResourceUsage(startTime);
11805
13655
  this.stats.convergenceInfo.converged = true;
13656
+ this.recordParetoMetrics(
13657
+ paretoFront.length,
13658
+ allSolutions.length,
13659
+ "base_optimizer",
13660
+ hypervolume
13661
+ );
11806
13662
  const bestScore = paretoFront.length > 0 ? Math.max(
11807
13663
  ...paretoFront.map((sol) => Math.max(...Object.values(sol.scores)))
11808
13664
  ) : 0;
@@ -12109,23 +13965,36 @@ var AxBaseOptimizer = class {
12109
13965
  async saveCheckpoint(optimizerType, optimizerConfig, bestScore, bestConfiguration, optimizerState = {}, options) {
12110
13966
  const saveFn = options?.overrideCheckpointSave || this.checkpointSave;
12111
13967
  if (!saveFn) return void 0;
12112
- const checkpoint = {
12113
- version: "1.0.0",
12114
- timestamp: Date.now(),
12115
- optimizerType,
12116
- optimizerConfig,
12117
- currentRound: this.currentRound,
12118
- totalRounds: this.stats.resourceUsage.totalTime > 0 ? this.currentRound : 0,
12119
- bestScore,
12120
- bestConfiguration,
12121
- scoreHistory: [...this.scoreHistory],
12122
- configurationHistory: [...this.configurationHistory],
12123
- stats: { ...this.stats },
12124
- optimizerState,
12125
- examples: this.examples,
12126
- validationSet: this.validationSet
12127
- };
12128
- return await saveFn(checkpoint);
13968
+ const startTime = Date.now();
13969
+ let success = false;
13970
+ let checkpointId;
13971
+ try {
13972
+ const checkpoint = {
13973
+ version: "1.0.0",
13974
+ timestamp: Date.now(),
13975
+ optimizerType,
13976
+ optimizerConfig,
13977
+ currentRound: this.currentRound,
13978
+ totalRounds: this.stats.resourceUsage.totalTime > 0 ? this.currentRound : 0,
13979
+ bestScore,
13980
+ bestConfiguration,
13981
+ scoreHistory: [...this.scoreHistory],
13982
+ configurationHistory: [...this.configurationHistory],
13983
+ stats: { ...this.stats },
13984
+ optimizerState,
13985
+ examples: this.examples,
13986
+ validationSet: this.validationSet
13987
+ };
13988
+ checkpointId = await saveFn(checkpoint);
13989
+ success = true;
13990
+ } catch (error) {
13991
+ success = false;
13992
+ throw error;
13993
+ } finally {
13994
+ const latency = Date.now() - startTime;
13995
+ this.recordCheckpointMetrics("save", latency, success, optimizerType);
13996
+ }
13997
+ return checkpointId;
12129
13998
  }
12130
13999
  /**
12131
14000
  * Load optimization state from checkpoint
@@ -12133,7 +14002,20 @@ var AxBaseOptimizer = class {
12133
14002
  async loadCheckpoint(checkpointId, options) {
12134
14003
  const loadFn = options?.overrideCheckpointLoad || this.checkpointLoad;
12135
14004
  if (!loadFn) return null;
12136
- return await loadFn(checkpointId);
14005
+ const startTime = Date.now();
14006
+ let success = false;
14007
+ let checkpoint = null;
14008
+ try {
14009
+ checkpoint = await loadFn(checkpointId);
14010
+ success = checkpoint !== null;
14011
+ } catch (error) {
14012
+ success = false;
14013
+ throw error;
14014
+ } finally {
14015
+ const latency = Date.now() - startTime;
14016
+ this.recordCheckpointMetrics("load", latency, success, "unknown");
14017
+ }
14018
+ return checkpoint;
12137
14019
  }
12138
14020
  /**
12139
14021
  * Restore optimizer state from checkpoint
@@ -12210,6 +14092,128 @@ var AxBaseOptimizer = class {
12210
14092
  }
12211
14093
  return this.verbose ?? true;
12212
14094
  }
14095
+ /**
14096
+ * Record optimization start metrics
14097
+ */
14098
+ recordOptimizationStart(optimizerType, programSignature) {
14099
+ if (!this.metricsInstruments) return;
14100
+ if (programSignature) {
14101
+ const inputFields = (programSignature.match(/input:/g) || []).length;
14102
+ const outputFields = (programSignature.match(/output:/g) || []).length;
14103
+ recordProgramComplexityMetric(
14104
+ this.metricsInstruments,
14105
+ inputFields,
14106
+ outputFields,
14107
+ this.examples.length,
14108
+ this.getValidationSet().length,
14109
+ optimizerType
14110
+ );
14111
+ }
14112
+ recordOptimizerConfigurationMetric(
14113
+ this.metricsInstruments,
14114
+ optimizerType,
14115
+ this.targetScore,
14116
+ void 0
14117
+ // maxRounds would be set by concrete optimizers
14118
+ );
14119
+ }
14120
+ /**
14121
+ * Record optimization completion metrics
14122
+ */
14123
+ recordOptimizationComplete(duration, success, optimizerType, programSignature) {
14124
+ if (!this.metricsInstruments) return;
14125
+ recordOptimizationMetric(
14126
+ this.metricsInstruments,
14127
+ duration,
14128
+ success,
14129
+ optimizerType,
14130
+ programSignature
14131
+ );
14132
+ recordOptimizationDurationMetric(
14133
+ this.metricsInstruments,
14134
+ duration,
14135
+ optimizerType
14136
+ );
14137
+ const currentCost = this.costTracker?.getCurrentCost() ?? 0;
14138
+ const totalTokens = this.costTracker?.getTotalTokens() ?? 0;
14139
+ recordResourceUsageMetric(
14140
+ this.metricsInstruments,
14141
+ totalTokens,
14142
+ currentCost,
14143
+ optimizerType
14144
+ );
14145
+ }
14146
+ /**
14147
+ * Record convergence metrics
14148
+ */
14149
+ recordConvergenceMetrics(rounds, currentScore, improvement, stagnationRounds, optimizerType) {
14150
+ if (!this.metricsInstruments) return;
14151
+ recordConvergenceMetric(
14152
+ this.metricsInstruments,
14153
+ rounds,
14154
+ currentScore,
14155
+ improvement,
14156
+ stagnationRounds,
14157
+ optimizerType
14158
+ );
14159
+ }
14160
+ /**
14161
+ * Record early stopping metrics
14162
+ */
14163
+ recordEarlyStoppingMetrics(reason, optimizerType) {
14164
+ if (!this.metricsInstruments) return;
14165
+ recordEarlyStoppingMetric(this.metricsInstruments, reason, optimizerType);
14166
+ }
14167
+ /**
14168
+ * Record teacher-student interaction metrics
14169
+ */
14170
+ recordTeacherStudentMetrics(latency, scoreImprovement, optimizerType) {
14171
+ if (!this.metricsInstruments) return;
14172
+ recordTeacherStudentMetric(
14173
+ this.metricsInstruments,
14174
+ latency,
14175
+ scoreImprovement,
14176
+ optimizerType
14177
+ );
14178
+ }
14179
+ /**
14180
+ * Record checkpoint metrics
14181
+ */
14182
+ recordCheckpointMetrics(operation, latency, success, optimizerType) {
14183
+ if (!this.metricsInstruments) return;
14184
+ recordCheckpointMetric(
14185
+ this.metricsInstruments,
14186
+ operation,
14187
+ latency,
14188
+ success,
14189
+ optimizerType
14190
+ );
14191
+ }
14192
+ /**
14193
+ * Record Pareto optimization metrics
14194
+ */
14195
+ recordParetoMetrics(frontSize, solutionsGenerated, optimizerType, hypervolume) {
14196
+ if (!this.metricsInstruments) return;
14197
+ recordParetoMetric(
14198
+ this.metricsInstruments,
14199
+ frontSize,
14200
+ solutionsGenerated,
14201
+ optimizerType,
14202
+ hypervolume
14203
+ );
14204
+ }
14205
+ /**
14206
+ * Record performance metrics
14207
+ */
14208
+ recordPerformanceMetrics(metricType, duration, optimizerType) {
14209
+ if (!this.metricsInstruments) return;
14210
+ recordOptimizerPerformanceMetric(
14211
+ this.metricsInstruments,
14212
+ metricType,
14213
+ duration,
14214
+ optimizerType
14215
+ );
14216
+ }
12213
14217
  };
12214
14218
 
12215
14219
  // db/base.ts
@@ -17752,10 +19756,15 @@ var AxRAG = class extends AxChainOfThought {
17752
19756
  axAITogetherDefaultConfig,
17753
19757
  axBaseAIDefaultConfig,
17754
19758
  axBaseAIDefaultCreativeConfig,
19759
+ axCheckMetricsHealth,
17755
19760
  axCreateDefaultLogger,
17756
19761
  axCreateDefaultTextLogger,
17757
19762
  axCreateOptimizerLogger,
19763
+ axDefaultMetricsConfig,
17758
19764
  axDefaultOptimizerLogger,
19765
+ axDefaultOptimizerMetricsConfig,
19766
+ axGetMetricsConfig,
19767
+ axGetOptimizerMetricsConfig,
17759
19768
  axGlobals,
17760
19769
  axModelInfoAnthropic,
17761
19770
  axModelInfoCohere,
@@ -17771,6 +19780,8 @@ var AxRAG = class extends AxChainOfThought {
17771
19780
  axModelInfoTogether,
17772
19781
  axSpanAttributes,
17773
19782
  axSpanEvents,
19783
+ axUpdateMetricsConfig,
19784
+ axUpdateOptimizerMetricsConfig,
17774
19785
  axValidateChatRequestMessage,
17775
19786
  axValidateChatResponseResult,
17776
19787
  f,