@marinoscar/kvox-eval 0.0.0-bootstrap → 0.1.0-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/LICENSE +21 -0
- package/README.md +166 -0
- package/dist/ask/index.d.ts +6 -0
- package/dist/ask/index.js +28 -0
- package/dist/ask/question-schema.d.ts +121 -0
- package/dist/ask/question-schema.js +167 -0
- package/dist/ask/report.d.ts +88 -0
- package/dist/ask/report.js +170 -0
- package/dist/ask/scorer.d.ts +104 -0
- package/dist/ask/scorer.js +164 -0
- package/dist/ask-run/ask-command.d.ts +62 -0
- package/dist/ask-run/ask-command.js +254 -0
- package/dist/ask-run/host/app.d.ts +65 -0
- package/dist/ask-run/host/app.js +146 -0
- package/dist/ask-run/host/db.d.ts +38 -0
- package/dist/ask-run/host/db.js +126 -0
- package/dist/ask-run/host/ports.d.ts +35 -0
- package/dist/ask-run/host/ports.js +113 -0
- package/dist/ask-run/index.d.ts +13 -0
- package/dist/ask-run/index.js +35 -0
- package/dist/ask-run/replay.d.ts +128 -0
- package/dist/ask-run/replay.js +212 -0
- package/dist/ask-run/run-ask-eval.d.ts +125 -0
- package/dist/ask-run/run-ask-eval.js +193 -0
- package/dist/ask-run/seed-golden-graph.d.ts +64 -0
- package/dist/ask-run/seed-golden-graph.js +495 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +12 -0
- package/dist/cli/kg-command.d.ts +66 -0
- package/dist/cli/kg-command.js +238 -0
- package/dist/cli/main.d.ts +18 -0
- package/dist/cli/main.js +69 -0
- package/dist/fixtures/domains.d.ts +16 -0
- package/dist/fixtures/domains.js +33 -0
- package/dist/fixtures/fixture-schema.d.ts +323 -0
- package/dist/fixtures/fixture-schema.js +199 -0
- package/dist/fixtures/index.d.ts +16 -0
- package/dist/fixtures/index.js +40 -0
- package/dist/fixtures/load.d.ts +73 -0
- package/dist/fixtures/load.js +137 -0
- package/dist/fixtures/questions.d.ts +15 -0
- package/dist/fixtures/questions.js +26 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +36 -0
- package/dist/kg/gold-runner.d.ts +13 -0
- package/dist/kg/gold-runner.js +57 -0
- package/dist/kg/index.d.ts +17 -0
- package/dist/kg/index.js +65 -0
- package/dist/kg/internals.d.ts +7 -0
- package/dist/kg/internals.js +17 -0
- package/dist/kg/prediction-schema.d.ts +245 -0
- package/dist/kg/prediction-schema.js +102 -0
- package/dist/kg/predictions.d.ts +11 -0
- package/dist/kg/predictions.js +49 -0
- package/dist/kg/report.d.ts +84 -0
- package/dist/kg/report.js +125 -0
- package/dist/kg/run-kg-eval.d.ts +77 -0
- package/dist/kg/run-kg-eval.js +137 -0
- package/dist/kg/runner.d.ts +72 -0
- package/dist/kg/runner.js +51 -0
- package/dist/kg/runners/extract-resolve-runner.d.ts +40 -0
- package/dist/kg/runners/extract-resolve-runner.js +199 -0
- package/dist/kg/runners/extract-runner.d.ts +65 -0
- package/dist/kg/runners/extract-runner.js +243 -0
- package/dist/kg/scorer.d.ts +226 -0
- package/dist/kg/scorer.js +463 -0
- package/dist/kg/targets.d.ts +17 -0
- package/dist/kg/targets.js +16 -0
- package/dist/kg/text.d.ts +45 -0
- package/dist/kg/text.js +100 -0
- package/dist/live/adapters.d.ts +16 -0
- package/dist/live/adapters.js +58 -0
- package/dist/live/env.d.ts +39 -0
- package/dist/live/env.js +56 -0
- package/dist/live/index.d.ts +6 -0
- package/dist/live/index.js +16 -0
- package/dist/live/live-ai.d.ts +104 -0
- package/dist/live/live-ai.js +157 -0
- package/dist/parity/constants.d.ts +79 -0
- package/dist/parity/constants.js +104 -0
- package/dist/parity/index.d.ts +20 -0
- package/dist/parity/index.js +38 -0
- package/dist/parity/internals.d.ts +8 -0
- package/dist/parity/internals.js +16 -0
- package/dist/parity/scenario.d.ts +45 -0
- package/dist/parity/scenario.js +245 -0
- package/dist/parity/script.d.ts +44 -0
- package/dist/parity/script.js +136 -0
- package/dist/parity/snapshot.d.ts +43 -0
- package/dist/parity/snapshot.js +71 -0
- package/dist/real-data/index.d.ts +2 -0
- package/dist/real-data/index.js +12 -0
- package/dist/real-data/real-data.d.ts +76 -0
- package/dist/real-data/real-data.js +156 -0
- package/fixtures/kg-golden/README.md +136 -0
- package/fixtures/kg-golden/ask-questions.json +458 -0
- package/fixtures/kg-golden/meetings/m01-northwind-pilot-kickoff.json +792 -0
- package/fixtures/kg-golden/meetings/m02-halden-migration-planning.json +814 -0
- package/fixtures/kg-golden/meetings/m03-larkspur-weekly-sync.json +601 -0
- package/fixtures/kg-golden/meetings/m04-corvid-intake-discovery.json +690 -0
- package/fixtures/kg-golden/meetings/m05-hosting-vendor-selection.json +631 -0
- package/fixtures/kg-golden/meetings/m06-northwind-floor-data-review.json +649 -0
- package/fixtures/kg-golden/meetings/m07-gullwing-intro-notes.json +428 -0
- package/fixtures/kg-golden/meetings/m08-halden-migration-checkpoint.json +672 -0
- package/fixtures/kg-golden/meetings/m09-northwind-platform-org-update.json +711 -0
- package/fixtures/kg-golden/meetings/m10-corvid-prototype-review.json +623 -0
- package/fixtures/kg-golden/meetings/m11-solvane-grid-dashboard-scoping.json +689 -0
- package/fixtures/kg-golden/meetings/m12-northwind-pilot-replan.json +681 -0
- package/fixtures/kg-golden/meetings/m13-halden-cutover-go-no-go.json +721 -0
- package/fixtures/kg-golden/meetings/m14-gullwing-discovery-readout.json +719 -0
- package/fixtures/kg-golden/meetings/m15-halden-handover-ravi-leaving.json +716 -0
- package/fixtures/kg-golden/meetings/m16-varden-claims-portal-intro.json +704 -0
- package/fixtures/kg-golden/meetings/m17-corvid-usability-debrief.json +572 -0
- package/fixtures/kg-golden/meetings/m18-hosting-decision-revisited.json +655 -0
- package/fixtures/kg-golden/meetings/m19-solvane-integration-kickoff.json +726 -0
- package/fixtures/kg-golden/meetings/m20-northwind-go-live-retro.json +673 -0
- package/fixtures/kg-golden/meetings/m21-quarterly-account-review.json +449 -0
- package/fixtures/kg-golden/meetings/m22-halden-intro-call-2020.json +558 -0
- package/fixtures/kg-golden/meetings/m23-gullwing-model-review.json +702 -0
- package/fixtures/kg-golden/meetings/m24-varden-discovery-midpoint.json +643 -0
- package/fixtures/kg-golden/meetings/m25-corvid-rollout-planning.json +642 -0
- package/fixtures/kg-golden/meetings/m26-larkspur-engineering-prep.json +695 -0
- package/fixtures/kg-golden/meetings/m27-solvane-phase-one-demo.json +649 -0
- package/fixtures/kg-golden/meetings/m28-northwind-building-5-scoping.json +715 -0
- package/fixtures/kg-golden/meetings/m29-halden-southern-cutover-review.json +752 -0
- package/fixtures/kg-golden/meetings/m30-varden-portal-build-kickoff.json +697 -0
- package/fixtures/kg-golden/meetings/m31-gullwing-rollout-renewal.json +681 -0
- package/fixtures/kg-golden/meetings/m32-brambleway-weekly-sync.json +472 -0
- package/fixtures/kg-golden/meetings/m33-nina-oliver-one-on-one.json +342 -0
- package/fixtures/kg-golden/meetings/m34-coffee-with-dana.json +249 -0
- package/fixtures/kg-golden/meetings/m35-brambleway-june-sync.json +553 -0
- package/fixtures/kg-golden/meetings/m36-copenhagen-conference-planning.json +296 -0
- package/host/generated/client.d.ts +1 -0
- package/host/generated/client.js +5 -0
- package/host/generated/default.d.ts +1 -0
- package/host/generated/default.js +5 -0
- package/host/generated/edge.d.ts +1 -0
- package/host/generated/edge.js +1658 -0
- package/host/generated/index-browser.js +1684 -0
- package/host/generated/index.d.ts +192335 -0
- package/host/generated/index.js +1658 -0
- package/host/generated/package.json +139 -0
- package/host/generated/query_compiler_fast_bg.js +2 -0
- package/host/generated/query_compiler_fast_bg.wasm +0 -0
- package/host/generated/query_compiler_fast_bg.wasm-base64.js +2 -0
- package/host/generated/runtime/client.d.ts +3433 -0
- package/host/generated/runtime/client.js +110 -0
- package/host/generated/runtime/index-browser.d.ts +90 -0
- package/host/generated/runtime/index-browser.js +6 -0
- package/host/generated/runtime/wasm-compiler-edge.js +100 -0
- package/host/generated/schema.prisma +6312 -0
- package/host/generated/wasm-edge-light-loader.mjs +5 -0
- package/host/generated/wasm-worker-loader.mjs +5 -0
- package/host/prisma/fragments/kvox.ask.prisma +126 -0
- package/host/prisma/fragments/kvox.graph.prisma +1073 -0
- package/host/prisma/fragments/kvox.notes.prisma +787 -0
- package/host/prisma/fragments/kvox.search.prisma +211 -0
- package/host/prisma/fragments/kvox.transcripts.prisma +790 -0
- package/host/prisma/kvox.lock +101 -0
- package/host/prisma/migrations/20240101000000_initial/migration.sql +297 -0
- package/host/prisma/migrations/20240101000001_add_personal_access_tokens/migration.sql +31 -0
- package/host/prisma/migrations/20240101000002_add_credentials/migration.sql +20 -0
- package/host/prisma/migrations/20240101000003_add_notification_deliveries/migration.sql +27 -0
- package/host/prisma/migrations/20240101000004_drop_stale_uuid_defaults/migration.sql +35 -0
- package/host/prisma/migrations/20240101000005_add_notifications/migration.sql +22 -0
- package/host/prisma/migrations/20240101000006_add_push_subscriptions/migration.sql +25 -0
- package/host/prisma/migrations/20240101000007_add_jobs/migration.sql +110 -0
- package/host/prisma/migrations/20240101000008_add_worker_nodes/migration.sql +90 -0
- package/host/prisma/migrations/20240101000009_add_database_backup_runs/migration.sql +104 -0
- package/host/prisma/migrations/20240101000010_add_notification_broadcasts/migration.sql +57 -0
- package/host/prisma/migrations/20240101000011_add_backup_run_job_link/migration.sql +87 -0
- package/host/prisma/migrations/20240101000012_add_job_node_secrets/migration.sql +61 -0
- package/host/prisma/migrations/20240101000013_add_backup_run_pg_dump_version/migration.sql +26 -0
- package/host/prisma/migrations/20240101000014_add_job_claim_token/migration.sql +92 -0
- package/host/prisma/migrations/20240101000015_add_ai_platform/migration.sql +108 -0
- package/host/prisma/migrations/20240101000016_revoke_viewer_ai_use/migration.sql +32 -0
- package/host/prisma/migrations/20240101000017_add_user_credentials/migration.sql +29 -0
- package/host/prisma/migrations/20240101000018_add_device_session_credential_link/migration.sql +52 -0
- package/host/prisma/migrations/20240101000019_add_worker_node_vitals/migration.sql +3 -0
- package/host/prisma/migrations/20240101000020_add_job_trace_context/migration.sql +6 -0
- package/host/prisma/migrations/20240101000021_add_retention_created_at_indexes/migration.sql +13 -0
- package/host/prisma/migrations/20240101000022_add_organizations/migration.sql +142 -0
- package/host/prisma/migrations/20240101000023_split_system_org_roles/migration.sql +131 -0
- package/host/prisma/migrations/20240101000024_org_scoped_rls/migration.sql +215 -0
- package/host/prisma/migrations/20240101000025_add_groups/migration.sql +165 -0
- package/host/prisma/migrations/20240101000026_add_grants/migration.sql +117 -0
- package/host/prisma/migrations/20240101000027_add_org_settings/migration.sql +49 -0
- package/host/prisma/migrations/20240101000028_add_org_credentials/migration.sql +54 -0
- package/host/prisma/migrations/20240101000029_add_jobs_org_id/migration.sql +18 -0
- package/host/prisma/migrations/20240101000030_add_jobs_org_id_status_index/migration.sql +6 -0
- package/host/prisma/migrations/20240101000031_add_broadcast_target_org/migration.sql +21 -0
- package/host/prisma/migrations/20240101000032_add_android_app/migration.sql +60 -0
- package/host/prisma/migrations/20240101000033_open_job_reason/migration.sql +16 -0
- package/host/prisma/migrations/20240101000034_ai_usage_feature/migration.sql +37 -0
- package/host/prisma/migrations/20240101000035_add_app_metadata/migration.sql +49 -0
- package/host/prisma/migrations/20240101000036_open_sharing_vocabularies/migration.sql +97 -0
- package/host/prisma/migrations/20260914130000_kvox_add_transcripts/migration.sql +322 -0
- package/host/prisma/migrations/20260914140000_kvox_add_notes/migration.sql +311 -0
- package/host/prisma/migrations/20260915120000_kvox_add_search_vectors/migration.sql +150 -0
- package/host/prisma/migrations/20260915130000_kvox_add_search_embeddings/migration.sql +362 -0
- package/host/prisma/migrations/20260915210000_kvox_add_note_title_source/migration.sql +30 -0
- package/host/prisma/migrations/20260923120000_kvox_add_note_generation_context_snapshot/migration.sql +24 -0
- package/host/prisma/migrations/20260923130000_kvox_add_user_hidden_note_templates/migration.sql +35 -0
- package/host/prisma/migrations/20260923140000_kvox_add_transcript_speaker_identities/migration.sql +6 -0
- package/host/prisma/migrations/20260923150000_kvox_transcript_name_checks/migration.sql +95 -0
- package/host/prisma/migrations/20260923160000_kvox_add_note_body_format/migration.sql +27 -0
- package/host/prisma/migrations/20260923170000_kvox_add_note_version_body_format/migration.sql +23 -0
- package/host/prisma/migrations/20260926012548_kvox_add_knowledge_graph/migration.sql +680 -0
- package/host/prisma/migrations/20260926030000_kvox_fix_kg_relations_valid_precision_chk/migration.sql +29 -0
- package/host/prisma/migrations/20260926030100_kvox_add_transcript_recorded_at/migration.sql +9 -0
- package/host/prisma/migrations/20260926030200_kvox_kg_evidence_invariant/migration.sql +60 -0
- package/host/prisma/migrations/20260926040000_kvox_add_kg_graph_layouts/migration.sql +30 -0
- package/host/prisma/migrations/20260926050000_kvox_add_ask_conversations/migration.sql +99 -0
- package/host/prisma/migrations/20260926231512_kvox_add_kg_exports/migration.sql +52 -0
- package/host/prisma/migrations/20261016120000_kvox_transcripts_org_id/migration.sql +49 -0
- package/host/prisma/platform.lock +319 -0
- package/host/prisma/schema/app.kvox.ask.prisma +110 -0
- package/host/prisma/schema/app.kvox.graph.prisma +1030 -0
- package/host/prisma/schema/app.kvox.notes.prisma +746 -0
- package/host/prisma/schema/app.kvox.search.prisma +208 -0
- package/host/prisma/schema/app.kvox.transcripts.prisma +726 -0
- package/host/prisma/schema/platform.ai.prisma +419 -0
- package/host/prisma/schema/platform.android-app.prisma +46 -0
- package/host/prisma/schema/platform.base.prisma +15 -0
- package/host/prisma/schema/platform.credentials.prisma +156 -0
- package/host/prisma/schema/platform.db-backup.prisma +359 -0
- package/host/prisma/schema/platform.identity.prisma +638 -0
- package/host/prisma/schema/platform.jobs.prisma +824 -0
- package/host/prisma/schema/platform.notifications.prisma +641 -0
- package/host/prisma/schema/platform.settings.prisma +53 -0
- package/host/prisma/schema/platform.sharing.prisma +208 -0
- package/host/prisma/schema/platform.storage.prisma +118 -0
- package/package.json +112 -1
- package/parity/requests.ask.json +2681 -0
- package/parity/requests.m01.json +1554 -0
- package/parity/requests.m02.json +1554 -0
- package/parity/requests.m03.json +1554 -0
- package/parity/requests.m04.json +1554 -0
- package/parity/requests.m05.json +1554 -0
- package/parity/requests.m06.json +1554 -0
- package/parity/requests.m07.json +1554 -0
- package/parity/requests.m08.json +1554 -0
- package/parity/requests.m09.json +1554 -0
- package/parity/requests.m10.json +1554 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// =============================================================================
|
|
3
|
+
// runAskEval: the Ask evaluation, headless (issue #608; the web app's runner #382)
|
|
4
|
+
// =============================================================================
|
|
5
|
+
//
|
|
6
|
+
// Starts the in-memory host (`host/app.ts`), seeds the golden graph under the
|
|
7
|
+
// evaluation user (`seed-golden-graph.ts`), then for every selected question:
|
|
8
|
+
//
|
|
9
|
+
// create a conversation (`AskConversationsService`) → post the question
|
|
10
|
+
// through the REAL `AskMessagesService` (checks, transaction, the real
|
|
11
|
+
// `ask.respond` job row) → invoke `AskRespondHandler.process(job)` DIRECTLY
|
|
12
|
+
// (nothing else claims the job) → read the finished assistant message back.
|
|
13
|
+
//
|
|
14
|
+
// The turn runs on the model port the caller hands in, exactly as a production
|
|
15
|
+
// turn runs on the host's binding: live, `createLiveKvoxAi` (`createKvoxAi`
|
|
16
|
+
// over the direct runtime and the provider adapters); replay, `createKvoxAi`
|
|
17
|
+
// over a scripted runtime (`replay.ts`). Every request the port receives is
|
|
18
|
+
// captured through a thin wrapper around its own `chat()` (never a second
|
|
19
|
+
// implementation), so the scorer's leak check sees exactly what left the run.
|
|
20
|
+
//
|
|
21
|
+
// EVERYTHING DIES WITH THE RUN: the database is PGlite in memory and `close()`
|
|
22
|
+
// runs in a `finally`, so there is nothing to tear down and no deployment
|
|
23
|
+
// setting to restore (the web app's runner had both).
|
|
24
|
+
// =============================================================================
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.DEFAULT_ASK_EVAL_MODEL = void 0;
|
|
27
|
+
exports.startAskEvalSession = startAskEvalSession;
|
|
28
|
+
exports.runAskEval = runAskEval;
|
|
29
|
+
const ask_1 = require("@marinoscar/kvox-api/ask");
|
|
30
|
+
const testing_1 = require("@marinoscar/kvox-api/ask/testing");
|
|
31
|
+
const ports_1 = require("@marinoscar/kvox-api/ports");
|
|
32
|
+
const index_js_1 = require("../ask/index.js");
|
|
33
|
+
const index_js_2 = require("../fixtures/index.js");
|
|
34
|
+
const app_js_1 = require("./host/app.js");
|
|
35
|
+
const seed_golden_graph_js_1 = require("./seed-golden-graph.js");
|
|
36
|
+
/**
|
|
37
|
+
* The model a live run uses when none is named.
|
|
38
|
+
*
|
|
39
|
+
* @stability experimental
|
|
40
|
+
*/
|
|
41
|
+
exports.DEFAULT_ASK_EVAL_MODEL = 'gpt-4o-mini';
|
|
42
|
+
/**
|
|
43
|
+
* Wraps the port's own `chat()` so every request is recorded. Mutates the port in
|
|
44
|
+
* place (the handler holds the same object); returns the restorer.
|
|
45
|
+
*/
|
|
46
|
+
function wrapChatForCapture(port, onRequest) {
|
|
47
|
+
const original = port.chat;
|
|
48
|
+
const bound = original.bind(port);
|
|
49
|
+
port.chat = (ctx, request) => {
|
|
50
|
+
const { signal: _signal, ...rest } = ctx;
|
|
51
|
+
onRequest({ ctx: rest, request });
|
|
52
|
+
return bound(ctx, request);
|
|
53
|
+
};
|
|
54
|
+
return () => {
|
|
55
|
+
port.chat = original;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Starts the host on `ai`, seeds the golden graph and returns a session that asks
|
|
60
|
+
* questions through the real Ask services and handler.
|
|
61
|
+
*
|
|
62
|
+
* @param options - the port, the fixtures (default: the whole golden set) and a progress sink.
|
|
63
|
+
* @returns the session; call `close()` when done (in a `finally`).
|
|
64
|
+
* @stability experimental
|
|
65
|
+
*/
|
|
66
|
+
async function startAskEvalSession(options) {
|
|
67
|
+
const log = options.log ?? (() => { });
|
|
68
|
+
const fixtures = options.fixtures ?? (0, index_js_2.loadGoldenSet)();
|
|
69
|
+
const host = await (0, app_js_1.startAskEvalHost)({ ai: options.ai, log });
|
|
70
|
+
let bucket = [];
|
|
71
|
+
let unwrap = null;
|
|
72
|
+
try {
|
|
73
|
+
const seeded = await (0, seed_golden_graph_js_1.seedGoldenGraph)(host, fixtures);
|
|
74
|
+
log(`seed: ${fixtures.length} meetings, ${seeded.counts.entities} entities, ${seeded.counts.relations} relations, ` +
|
|
75
|
+
`${seeded.counts.items} items, ${seeded.counts.evidence} citations` +
|
|
76
|
+
(seeded.refusals.length ? `, ${seeded.refusals.length} refused` : '') +
|
|
77
|
+
(seeded.warnings.length ? `, ${seeded.warnings.length} warning(s)` : ''));
|
|
78
|
+
for (const r of seeded.refusals)
|
|
79
|
+
log(`seed refused: ${r.fixtureId} ${r.row}: ${r.reason}`);
|
|
80
|
+
for (const w of seeded.warnings)
|
|
81
|
+
log(`seed warning: ${w}`);
|
|
82
|
+
const conversations = host.resolve(ask_1.AskConversationsService);
|
|
83
|
+
const messages = host.resolve(testing_1.internals.AskMessagesService);
|
|
84
|
+
const handler = host.resolve(testing_1.internals.AskRespondHandler);
|
|
85
|
+
unwrap = wrapChatForCapture(host.ai, (captured) => bucket.push(captured));
|
|
86
|
+
let closed = false;
|
|
87
|
+
return {
|
|
88
|
+
host,
|
|
89
|
+
seeded,
|
|
90
|
+
async ask(question, model) {
|
|
91
|
+
bucket = [];
|
|
92
|
+
const started = Date.now();
|
|
93
|
+
const conversation = await conversations.create(host.userId, {});
|
|
94
|
+
const posted = await messages.post(host.userId, conversation.id, { content: question, model });
|
|
95
|
+
const row = await host.prisma.askMessage.findUniqueOrThrow({ where: { id: posted.assistantMessage.id } });
|
|
96
|
+
const job = await host.prisma.job.findUniqueOrThrow({ where: { id: row.jobId } });
|
|
97
|
+
let modelError;
|
|
98
|
+
try {
|
|
99
|
+
await handler.process({
|
|
100
|
+
id: job.id,
|
|
101
|
+
type: job.type,
|
|
102
|
+
subjectType: job.subjectType,
|
|
103
|
+
subjectId: job.subjectId,
|
|
104
|
+
payload: job.payload,
|
|
105
|
+
attempts: job.attempts,
|
|
106
|
+
orgId: job.orgId,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
// A failed model call: the handler has marked the turn `failed` and
|
|
111
|
+
// rethrown for the queue (which would record the attempt). This run is
|
|
112
|
+
// the queue; it records the class and goes on. A rate limit before any
|
|
113
|
+
// text leaves the turn `pending` for a re-run, which a run cannot wait
|
|
114
|
+
// for, so it (and anything else) stops the run.
|
|
115
|
+
if (!(error instanceof ports_1.KvoxAiError))
|
|
116
|
+
throw error;
|
|
117
|
+
const settled = await host.prisma.askMessage.findUniqueOrThrow({ where: { id: posted.assistantMessage.id }, select: { status: true } });
|
|
118
|
+
if (settled.status !== 'failed')
|
|
119
|
+
throw error;
|
|
120
|
+
modelError = { errorClass: error.errorClass };
|
|
121
|
+
}
|
|
122
|
+
const finished = await host.prisma.askMessage.findUniqueOrThrow({ where: { id: posted.assistantMessage.id } });
|
|
123
|
+
return {
|
|
124
|
+
message: testing_1.internals.toAskMessage(finished),
|
|
125
|
+
capturedPrompts: bucket.map((r) => JSON.stringify(r)),
|
|
126
|
+
ms: Date.now() - started,
|
|
127
|
+
...(modelError ? { modelError } : {}),
|
|
128
|
+
};
|
|
129
|
+
},
|
|
130
|
+
async close() {
|
|
131
|
+
if (closed)
|
|
132
|
+
return;
|
|
133
|
+
closed = true;
|
|
134
|
+
unwrap?.();
|
|
135
|
+
await host.close();
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
unwrap?.();
|
|
141
|
+
await host.close();
|
|
142
|
+
throw error;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/** The committed questions, narrowed to `ids`. */
|
|
146
|
+
function resolveQuestions(questions) {
|
|
147
|
+
if (questions === undefined)
|
|
148
|
+
return (0, index_js_2.loadGoldenAskQuestions)();
|
|
149
|
+
if (questions.every((q) => typeof q === 'string')) {
|
|
150
|
+
return (0, index_js_1.selectAskEvalQuestions)((0, index_js_2.loadGoldenAskQuestions)(), [...questions], null);
|
|
151
|
+
}
|
|
152
|
+
return [...questions];
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Runs the Ask evaluation headless: an in-memory PostgreSQL, the golden graph
|
|
156
|
+
* seeded through the graph write service, every question through the real
|
|
157
|
+
* `ask.respond` handler on `ai`, each answer scored.
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```ts
|
|
161
|
+
* const key = readEvalApiKey(process.env);
|
|
162
|
+
* const { ai } = createLiveKvoxAi({ provider: 'openai', model: 'gpt-4o-mini', apiKey: key?.apiKey ?? null });
|
|
163
|
+
* const run = await runAskEval({ ai, model: 'gpt-4o-mini', questions: ['q01', 'q07'] });
|
|
164
|
+
* console.log(formatAskEvalReport(run.report));
|
|
165
|
+
* ```
|
|
166
|
+
*
|
|
167
|
+
* @param options - the port, the model, the questions and the gate.
|
|
168
|
+
* @returns the answers, the id map, the scores and the report.
|
|
169
|
+
* @throws `AskEvalQuestionLoadError` for an unknown question id; `KgEvalLoadError` for a malformed fixture.
|
|
170
|
+
* @stability experimental
|
|
171
|
+
*/
|
|
172
|
+
async function runAskEval(options) {
|
|
173
|
+
const log = options.log ?? (() => { });
|
|
174
|
+
const questions = resolveQuestions(options.questions);
|
|
175
|
+
const session = await startAskEvalSession({ ai: options.ai, ...(options.fixtures ? { fixtures: options.fixtures } : {}), log });
|
|
176
|
+
try {
|
|
177
|
+
const results = [];
|
|
178
|
+
for (const question of questions) {
|
|
179
|
+
const answered = await session.ask(question.question, options.model);
|
|
180
|
+
log(`ask: ${question.id} ${answered.message.status} in ${answered.ms} ms` +
|
|
181
|
+
(answered.modelError ? ` (model call failed: ${answered.modelError.errorClass})` : ''));
|
|
182
|
+
results.push({ question, ...answered });
|
|
183
|
+
}
|
|
184
|
+
const idMap = session.seeded.idMap;
|
|
185
|
+
const scores = results.map((r) => (0, index_js_1.scoreAnswer)(r.question, r.message, r.capturedPrompts, idMap.evidenceSource, { ms: r.ms }));
|
|
186
|
+
const report = (0, index_js_1.buildAskEvalReport)(scores, { model: options.model, minMatch: options.minMatch ?? 0.8 });
|
|
187
|
+
const { refusals, warnings, counts } = session.seeded;
|
|
188
|
+
return { results, idMap, seed: { refusals, warnings, counts }, scores, report };
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
await session.close();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type GoldenFixture } from '../fixtures/index.js';
|
|
2
|
+
import type { AskEvalHost } from './host/app.js';
|
|
3
|
+
/**
|
|
4
|
+
* Fixture ids and labels ↔ the database rows the seeder wrote for them.
|
|
5
|
+
*
|
|
6
|
+
* @stability experimental
|
|
7
|
+
*/
|
|
8
|
+
export interface AskEvalIdMap {
|
|
9
|
+
/** `"m01-s009"` → the real `transcript_segments.id`. */
|
|
10
|
+
segments: Map<string, string>;
|
|
11
|
+
/** Fixture id → that meeting's `notes.id`. */
|
|
12
|
+
notes: Map<string, string>;
|
|
13
|
+
/** A global (`knownEntities`) id → `kg_entities.id`. Mostly for debugging. */
|
|
14
|
+
entities: Map<string, string>;
|
|
15
|
+
/** `kg_evidence.id` → `"m01-s009"` or `"m01#note"`: what the scorer's `citeFrom` checks resolve against. */
|
|
16
|
+
evidenceSource: Map<string, string>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* One row the write service refused: which fixture and row, and why (the
|
|
20
|
+
* service's message and issue paths; never a label, statement or quote).
|
|
21
|
+
*
|
|
22
|
+
* @stability experimental
|
|
23
|
+
*/
|
|
24
|
+
export interface AskEvalSeedRefusal {
|
|
25
|
+
/** The fixture id (`"m07"`). */
|
|
26
|
+
fixtureId: string;
|
|
27
|
+
/** The row, by kind, position and type key (`"relation #2 (WORKS_AT)"`). */
|
|
28
|
+
row: string;
|
|
29
|
+
/** The service's reason. */
|
|
30
|
+
reason: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* What {@link seedGoldenGraph} wrote.
|
|
34
|
+
*
|
|
35
|
+
* @stability experimental
|
|
36
|
+
*/
|
|
37
|
+
export interface SeededGoldenGraph {
|
|
38
|
+
/** The owner of every row (the host's evaluation user). */
|
|
39
|
+
userId: string;
|
|
40
|
+
/** Fixture ids ↔ row ids. */
|
|
41
|
+
idMap: AskEvalIdMap;
|
|
42
|
+
/** Rows the write service refused (skipped, reported). */
|
|
43
|
+
refusals: AskEvalSeedRefusal[];
|
|
44
|
+
/** Fixture data that could not be resolved (an unknown segment or entity reference). */
|
|
45
|
+
warnings: string[];
|
|
46
|
+
/** Row counts, for the log. */
|
|
47
|
+
counts: {
|
|
48
|
+
entities: number;
|
|
49
|
+
relations: number;
|
|
50
|
+
items: number;
|
|
51
|
+
evidence: number;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Seeds the evaluation user's entire gold graph from EVERY fixture in
|
|
56
|
+
* `fixtures` (pass the full loaded set: `loadGoldenSet()`), one transaction per
|
|
57
|
+
* fixture, in fixture id order, through `GraphWriteService`.
|
|
58
|
+
*
|
|
59
|
+
* @param host - the running host (its client, user and organization, and the write service).
|
|
60
|
+
* @param fixtures - the golden meetings.
|
|
61
|
+
* @returns the id map the scorer needs, the refusals and the warnings.
|
|
62
|
+
* @stability experimental
|
|
63
|
+
*/
|
|
64
|
+
export declare function seedGoldenGraph(host: AskEvalHost, fixtures: readonly GoldenFixture[]): Promise<SeededGoldenGraph>;
|