@memograph/cli 0.1.4

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.
Files changed (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +402 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +97 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/core/detect.d.ts +30 -0
  8. package/dist/core/detect.d.ts.map +1 -0
  9. package/dist/core/detect.js +212 -0
  10. package/dist/core/detect.js.map +1 -0
  11. package/dist/core/extract.d.ts +6 -0
  12. package/dist/core/extract.d.ts.map +1 -0
  13. package/dist/core/extract.js +104 -0
  14. package/dist/core/extract.js.map +1 -0
  15. package/dist/core/inspect.d.ts +7 -0
  16. package/dist/core/inspect.d.ts.map +1 -0
  17. package/dist/core/inspect.js +98 -0
  18. package/dist/core/inspect.js.map +1 -0
  19. package/dist/core/llm/client.d.ts +55 -0
  20. package/dist/core/llm/client.d.ts.map +1 -0
  21. package/dist/core/llm/client.js +199 -0
  22. package/dist/core/llm/client.js.map +1 -0
  23. package/dist/core/llm/detect-llm.d.ts +28 -0
  24. package/dist/core/llm/detect-llm.d.ts.map +1 -0
  25. package/dist/core/llm/detect-llm.js +212 -0
  26. package/dist/core/llm/detect-llm.js.map +1 -0
  27. package/dist/core/llm/extract-llm.d.ts +27 -0
  28. package/dist/core/llm/extract-llm.d.ts.map +1 -0
  29. package/dist/core/llm/extract-llm.js +151 -0
  30. package/dist/core/llm/extract-llm.js.map +1 -0
  31. package/dist/core/llm/prompts.d.ts +28 -0
  32. package/dist/core/llm/prompts.d.ts.map +1 -0
  33. package/dist/core/llm/prompts.js +172 -0
  34. package/dist/core/llm/prompts.js.map +1 -0
  35. package/dist/core/llm/providers.d.ts +34 -0
  36. package/dist/core/llm/providers.d.ts.map +1 -0
  37. package/dist/core/llm/providers.js +169 -0
  38. package/dist/core/llm/providers.js.map +1 -0
  39. package/dist/core/load.d.ts +10 -0
  40. package/dist/core/load.d.ts.map +1 -0
  41. package/dist/core/load.js +106 -0
  42. package/dist/core/load.js.map +1 -0
  43. package/dist/core/normalize.d.ts +30 -0
  44. package/dist/core/normalize.d.ts.map +1 -0
  45. package/dist/core/normalize.js +63 -0
  46. package/dist/core/normalize.js.map +1 -0
  47. package/dist/core/render.d.ts +10 -0
  48. package/dist/core/render.d.ts.map +1 -0
  49. package/dist/core/render.js +60 -0
  50. package/dist/core/render.js.map +1 -0
  51. package/dist/core/score.d.ts +27 -0
  52. package/dist/core/score.d.ts.map +1 -0
  53. package/dist/core/score.js +59 -0
  54. package/dist/core/score.js.map +1 -0
  55. package/dist/core/types.d.ts +162 -0
  56. package/dist/core/types.d.ts.map +1 -0
  57. package/dist/core/types.js +6 -0
  58. package/dist/core/types.js.map +1 -0
  59. package/dist/interactive/index.d.ts +67 -0
  60. package/dist/interactive/index.d.ts.map +1 -0
  61. package/dist/interactive/index.js +794 -0
  62. package/dist/interactive/index.js.map +1 -0
  63. package/dist/interactive/settings.d.ts +36 -0
  64. package/dist/interactive/settings.d.ts.map +1 -0
  65. package/dist/interactive/settings.js +174 -0
  66. package/dist/interactive/settings.js.map +1 -0
  67. package/dist/interactive/wizard.d.ts +10 -0
  68. package/dist/interactive/wizard.d.ts.map +1 -0
  69. package/dist/interactive/wizard.js +249 -0
  70. package/dist/interactive/wizard.js.map +1 -0
  71. package/package.json +49 -0
@@ -0,0 +1,199 @@
1
+ "use strict";
2
+ /**
3
+ * LLM Client - Unified interface for multiple LLM providers
4
+ */
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.LLMClient = void 0;
10
+ exports.createLLMClient = createLLMClient;
11
+ const openai_1 = __importDefault(require("openai"));
12
+ const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
13
+ const providers_js_1 = require("./providers.js");
14
+ /**
15
+ * Unified LLM client supporting multiple providers
16
+ */
17
+ class LLMClient {
18
+ openaiClient;
19
+ anthropicClient;
20
+ config;
21
+ constructor(config) {
22
+ this.config = config;
23
+ // Validate API key is present (for providers that need it)
24
+ const providerInfo = providers_js_1.PROVIDERS[config.provider];
25
+ const needsApiKey = providerInfo?.needsApiKey ?? true;
26
+ if (needsApiKey) {
27
+ if (config.provider === 'anthropic') {
28
+ const apiKey = config.apiKey || process.env.ANTHROPIC_API_KEY;
29
+ if (!apiKey) {
30
+ throw new Error('Anthropic API key not found. Set ANTHROPIC_API_KEY environment variable or provide --llm-api-key');
31
+ }
32
+ this.anthropicClient = new sdk_1.default({
33
+ apiKey,
34
+ baseURL: config.baseUrl || providerInfo.defaultBaseUrl,
35
+ });
36
+ }
37
+ else {
38
+ // All other providers use OpenAI-compatible client
39
+ // For openai provider, check OPENAI_API_KEY, otherwise check llm.apiKey
40
+ let apiKey = config.apiKey;
41
+ if (!apiKey) {
42
+ apiKey = config.provider === 'openai' ? process.env.OPENAI_API_KEY : process.env.LLM_API_KEY;
43
+ }
44
+ if (!apiKey && needsApiKey) {
45
+ const providerLabel = providerInfo?.label || config.provider;
46
+ throw new Error(`${providerLabel} API key not found. Provide it via environment variables or settings`);
47
+ }
48
+ this.openaiClient = new openai_1.default({
49
+ apiKey: apiKey || 'dummy', // OpenAI SDK requires a key even if unused (local providers)
50
+ baseURL: config.baseUrl || providerInfo.defaultBaseUrl,
51
+ });
52
+ }
53
+ }
54
+ else {
55
+ // Local providers that don't need API key
56
+ this.openaiClient = new openai_1.default({
57
+ apiKey: 'dummy', // OpenAI SDK requires a key
58
+ baseURL: config.baseUrl || providerInfo.defaultBaseUrl,
59
+ });
60
+ }
61
+ }
62
+ /**
63
+ * Generate a completion from the LLM
64
+ */
65
+ async complete(prompt, systemPrompt) {
66
+ const model = this.config.model || this.getDefaultModel();
67
+ if (this.config.provider === 'anthropic') {
68
+ return this.completeAnthropic(prompt, systemPrompt, model);
69
+ }
70
+ else if ((0, providers_js_1.isOpenAICompatible)(this.config.provider) || this.openaiClient) {
71
+ return this.completeOpenAI(prompt, systemPrompt, model);
72
+ }
73
+ throw new Error(`Unsupported provider: ${this.config.provider}`);
74
+ }
75
+ /**
76
+ * OpenAI completion
77
+ */
78
+ async completeOpenAI(prompt, systemPrompt, model) {
79
+ if (!this.openaiClient) {
80
+ throw new Error('OpenAI client not initialized');
81
+ }
82
+ const response = await this.openaiClient.chat.completions.create({
83
+ model,
84
+ messages: systemPrompt
85
+ ? [{ role: 'system', content: systemPrompt }, { role: 'user', content: prompt }]
86
+ : [{ role: 'user', content: prompt }],
87
+ temperature: this.config.temperature ?? 0.3,
88
+ max_tokens: this.config.maxTokens ?? 4096,
89
+ });
90
+ const choice = response.choices[0];
91
+ if (!choice || !choice.message) {
92
+ throw new Error('No completion returned from OpenAI');
93
+ }
94
+ return {
95
+ content: choice.message.content ?? '',
96
+ model: response.model,
97
+ usage: response.usage
98
+ ? {
99
+ promptTokens: response.usage.prompt_tokens,
100
+ completionTokens: response.usage.completion_tokens,
101
+ totalTokens: response.usage.total_tokens,
102
+ }
103
+ : undefined,
104
+ };
105
+ }
106
+ /**
107
+ * Anthropic completion
108
+ */
109
+ async completeAnthropic(prompt, systemPrompt, model) {
110
+ if (!this.anthropicClient) {
111
+ throw new Error('Anthropic client not initialized');
112
+ }
113
+ const response = await this.anthropicClient.messages.create({
114
+ model,
115
+ max_tokens: this.config.maxTokens ?? 4096,
116
+ system: systemPrompt,
117
+ messages: [{ role: 'user', content: prompt }],
118
+ temperature: this.config.temperature ?? 0.3,
119
+ });
120
+ const block = response.content[0];
121
+ if (block.type !== 'text') {
122
+ throw new Error('Non-text response from Anthropic');
123
+ }
124
+ return {
125
+ content: block.text,
126
+ model: response.model,
127
+ usage: {
128
+ promptTokens: response.usage.input_tokens,
129
+ completionTokens: response.usage.output_tokens,
130
+ totalTokens: response.usage.input_tokens + response.usage.output_tokens,
131
+ },
132
+ };
133
+ }
134
+ /**
135
+ * Get default model for each provider
136
+ */
137
+ getDefaultModel() {
138
+ // Use first model from presets if available, otherwise use provider name
139
+ const providerInfo = providers_js_1.PROVIDERS[this.config.provider];
140
+ if (providerInfo?.modelPresets && providerInfo.modelPresets.length > 0) {
141
+ return providerInfo.modelPresets[0];
142
+ }
143
+ // Fallback defaults
144
+ const fallbacks = {
145
+ openai: 'gpt-4o-mini',
146
+ anthropic: 'claude-3-5-sonnet-20241022',
147
+ gemini: 'gemini-1.5-flash',
148
+ mistral: 'mistral-small',
149
+ cohere: 'command-r',
150
+ xai: 'grok-2',
151
+ perplexity: 'sonar',
152
+ openrouter: 'openai/gpt-4o-mini',
153
+ together: 'meta-llama/Llama-3.1-70b-instruct',
154
+ groq: 'llama-3.1-70b-versatile',
155
+ fireworks: 'accounts/fireworks/models/llama-v3p-70b-instruct',
156
+ deepseek: 'deepseek-chat',
157
+ ollama: 'llama3',
158
+ lmstudio: 'llama3',
159
+ vllm: 'llama3',
160
+ localai: 'llama3',
161
+ openai_compatible: 'gpt-4o-mini',
162
+ };
163
+ return fallbacks[this.config.provider];
164
+ }
165
+ /**
166
+ * Test the connection
167
+ */
168
+ async test() {
169
+ try {
170
+ const response = await this.complete('Hello', 'You are a helpful assistant.');
171
+ return response.content.length > 0;
172
+ }
173
+ catch (error) {
174
+ console.error('LLM connection test failed:', error);
175
+ return false;
176
+ }
177
+ }
178
+ }
179
+ exports.LLMClient = LLMClient;
180
+ /**
181
+ * Create LLM client from environment or explicit config
182
+ */
183
+ function createLLMClient(config) {
184
+ const provider = (config?.provider || process.env.LLM_PROVIDER || 'openai');
185
+ const apiKey = config?.apiKey;
186
+ const model = config?.model || process.env.LLM_MODEL;
187
+ const temperature = config?.temperature;
188
+ const maxTokens = config?.maxTokens;
189
+ const baseUrl = config?.baseUrl || process.env.LLM_BASE_URL;
190
+ return new LLMClient({
191
+ provider,
192
+ apiKey,
193
+ model,
194
+ temperature,
195
+ maxTokens,
196
+ baseUrl,
197
+ });
198
+ }
199
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/core/llm/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * LLM-based drift detection
3
+ */
4
+ import { TranscriptMessage, DriftEvent, ExtractedFact } from '../types.js';
5
+ import { LLMClient } from './client.js';
6
+ export interface DetectDriftLLMResult {
7
+ events: DriftEvent[];
8
+ drift_score?: number;
9
+ timing_ms: number;
10
+ usage?: {
11
+ promptTokens: number;
12
+ completionTokens: number;
13
+ totalTokens: number;
14
+ };
15
+ }
16
+ /**
17
+ * Detect drift events using LLM
18
+ */
19
+ export declare function detectDriftLLM(messages: TranscriptMessage[], facts: ExtractedFact[], llmClient: LLMClient): Promise<DetectDriftLLMResult>;
20
+ /**
21
+ * Detect drift events from raw transcript text using LLM
22
+ */
23
+ export declare function detectDriftLLMFromRaw(rawText: string, facts: ExtractedFact[], llmClient: LLMClient): Promise<DetectDriftLLMResult>;
24
+ /**
25
+ * Detect drift events in batches for large transcripts
26
+ */
27
+ export declare function detectDriftLLMBatched(messages: TranscriptMessage[], facts: ExtractedFact[], llmClient: LLMClient, batchSize?: number): Promise<DetectDriftLLMResult>;
28
+ //# sourceMappingURL=detect-llm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-llm.d.ts","sourceRoot":"","sources":["../../../src/core/llm/detect-llm.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,iBAAiB,EACjB,UAAU,EACV,aAAa,EAKd,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOxC,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,KAAK,EAAE,aAAa,EAAE,EACtB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,oBAAoB,CAAC,CA6D/B;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,aAAa,EAAE,EACtB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,oBAAoB,CAAC,CAgD/B;AA8ED;;GAEG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,KAAK,EAAE,aAAa,EAAE,EACtB,SAAS,EAAE,SAAS,EACpB,SAAS,SAAM,GACd,OAAO,CAAC,oBAAoB,CAAC,CAkD/B"}
@@ -0,0 +1,212 @@
1
+ "use strict";
2
+ /**
3
+ * LLM-based drift detection
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.detectDriftLLM = detectDriftLLM;
7
+ exports.detectDriftLLMFromRaw = detectDriftLLMFromRaw;
8
+ exports.detectDriftLLMBatched = detectDriftLLMBatched;
9
+ const prompts_js_1 = require("./prompts.js");
10
+ /**
11
+ * Detect drift events using LLM
12
+ */
13
+ async function detectDriftLLM(messages, facts, llmClient) {
14
+ const start = performance.now();
15
+ // Format messages for the prompt
16
+ const formattedMessages = messages.map(m => `[${m.idx}] ${m.role}: ${m.content}`);
17
+ // Format facts
18
+ const formattedFacts = facts.length > 0
19
+ ? facts.map(f => `- ${f.fact_key} = ${f.fact_value} (msg ${f.msg_idx}, confidence: ${f.confidence})`).join('\n')
20
+ : 'No facts extracted';
21
+ try {
22
+ // Call LLM
23
+ const prompt = (0, prompts_js_1.createDriftDetectionPrompt)(formattedMessages, formattedFacts);
24
+ const response = await llmClient.complete(prompt, prompts_js_1.DRIFT_DETECTION_SYSTEM);
25
+ // Parse and validate response
26
+ let llmResponse;
27
+ try {
28
+ llmResponse = JSON.parse(response.content);
29
+ }
30
+ catch (parseError) {
31
+ throw new Error(`Failed to parse LLM response as JSON: ${parseError.message}\n` +
32
+ `Response content: ${response.content.substring(0, 200)}...`);
33
+ }
34
+ // Validate response structure
35
+ if (!llmResponse || typeof llmResponse !== 'object') {
36
+ throw new Error('LLM response is not a valid object');
37
+ }
38
+ if (!Array.isArray(llmResponse.events)) {
39
+ throw new Error('LLM response does not contain an events array');
40
+ }
41
+ const rawEvents = llmResponse.events;
42
+ // Extract drift score if provided
43
+ let drift_score = undefined;
44
+ if (typeof llmResponse.drift_score === 'number') {
45
+ drift_score = Math.max(0, Math.min(100, llmResponse.drift_score));
46
+ }
47
+ // Map to DriftEvent types
48
+ const events = rawEvents.map((event) => mapLLMEventToDriftEvent(event, messages));
49
+ return {
50
+ events,
51
+ drift_score,
52
+ timing_ms: performance.now() - start,
53
+ usage: response.usage,
54
+ };
55
+ }
56
+ catch (error) {
57
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
58
+ throw new Error(`LLM drift detection failed: ${errorMessage}`);
59
+ }
60
+ }
61
+ /**
62
+ * Detect drift events from raw transcript text using LLM
63
+ */
64
+ async function detectDriftLLMFromRaw(rawText, facts, llmClient) {
65
+ const start = performance.now();
66
+ const formattedFacts = facts.length > 0
67
+ ? facts.map(f => `- ${f.fact_key} = ${f.fact_value} (confidence: ${f.confidence})`).join('\n')
68
+ : 'No facts extracted';
69
+ try {
70
+ const prompt = (0, prompts_js_1.createDriftDetectionPromptFromRaw)(rawText, formattedFacts);
71
+ const response = await llmClient.complete(prompt, prompts_js_1.DRIFT_DETECTION_SYSTEM);
72
+ let llmResponse;
73
+ try {
74
+ llmResponse = JSON.parse(response.content);
75
+ }
76
+ catch (parseError) {
77
+ throw new Error(`Failed to parse LLM response as JSON: ${parseError.message}\n` +
78
+ `Response content: ${response.content.substring(0, 200)}...`);
79
+ }
80
+ if (!llmResponse || typeof llmResponse !== 'object') {
81
+ throw new Error('LLM response is not a valid object');
82
+ }
83
+ if (!Array.isArray(llmResponse.events)) {
84
+ throw new Error('LLM response does not contain an events array');
85
+ }
86
+ let drift_score = undefined;
87
+ if (typeof llmResponse.drift_score === 'number') {
88
+ drift_score = Math.max(0, Math.min(100, llmResponse.drift_score));
89
+ }
90
+ const events = llmResponse.events.map((event) => mapLLMEventToDriftEvent(event, []));
91
+ return {
92
+ events,
93
+ drift_score,
94
+ timing_ms: performance.now() - start,
95
+ usage: response.usage,
96
+ };
97
+ }
98
+ catch (error) {
99
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
100
+ throw new Error(`LLM drift detection failed: ${errorMessage}`);
101
+ }
102
+ }
103
+ /**
104
+ * Map LLM event to DriftEvent type
105
+ */
106
+ function mapLLMEventToDriftEvent(event, messages) {
107
+ const baseEvent = {
108
+ severity: Math.max(1, Math.min(5, event.severity || 3)),
109
+ confidence: Math.max(0, Math.min(1, event.confidence || 0.5)),
110
+ evidence: {
111
+ msg_idxs: event.msg_idxs || [],
112
+ snippets: event.snippets || [],
113
+ context: event.details,
114
+ },
115
+ summary: event.summary || 'No summary provided',
116
+ };
117
+ switch (event.type) {
118
+ case 'repetition_cluster':
119
+ return {
120
+ type: 'repetition_cluster',
121
+ ...baseEvent,
122
+ cluster_size: event.msg_idxs?.length || 2,
123
+ };
124
+ case 'session_reset':
125
+ return {
126
+ type: 'session_reset',
127
+ ...baseEvent,
128
+ reset_phrase: event.details?.reset_phrase || 'reset',
129
+ };
130
+ case 'preference_forgotten':
131
+ return {
132
+ type: 'preference_forgotten',
133
+ ...baseEvent,
134
+ preference_key: event.details?.preference_key || 'unknown',
135
+ preference_value: event.details?.preference_value || 'unknown',
136
+ };
137
+ case 'contradiction':
138
+ return {
139
+ type: 'contradiction',
140
+ ...baseEvent,
141
+ old_value: event.details?.old_value || 'unknown',
142
+ new_value: event.details?.new_value || 'unknown',
143
+ };
144
+ // For new event types not in the original DriftEvent union,
145
+ // we'll map them to existing types with appropriate defaults
146
+ case 'context_loss':
147
+ return {
148
+ type: 'session_reset', // Map to session_reset as closest match
149
+ ...baseEvent,
150
+ reset_phrase: 'context lost',
151
+ };
152
+ case 'inconsistent_behavior':
153
+ return {
154
+ type: 'preference_forgotten', // Map to preference_forgotten as closest match
155
+ ...baseEvent,
156
+ preference_key: 'behavior',
157
+ preference_value: 'inconsistent',
158
+ };
159
+ default:
160
+ // Default to session_reset for unknown types
161
+ return {
162
+ type: 'session_reset',
163
+ ...baseEvent,
164
+ reset_phrase: 'unknown drift',
165
+ };
166
+ }
167
+ }
168
+ /**
169
+ * Detect drift events in batches for large transcripts
170
+ */
171
+ async function detectDriftLLMBatched(messages, facts, llmClient, batchSize = 100) {
172
+ const start = performance.now();
173
+ const allEvents = [];
174
+ const driftScores = [];
175
+ let totalUsage = {
176
+ promptTokens: 0,
177
+ completionTokens: 0,
178
+ totalTokens: 0,
179
+ };
180
+ // Process in batches
181
+ for (let i = 0; i < messages.length; i += batchSize) {
182
+ const batchMessages = messages.slice(i, i + batchSize);
183
+ const batchStartIdx = batchMessages[0]?.idx || 0;
184
+ const batchEndIdx = batchMessages[batchMessages.length - 1]?.idx || batchStartIdx;
185
+ // Filter facts to those in this batch
186
+ const batchFacts = facts.filter(f => f.msg_idx >= batchStartIdx && f.msg_idx <= batchEndIdx);
187
+ const result = await detectDriftLLM(batchMessages, batchFacts, llmClient);
188
+ // No index adjustment needed - LLM returns actual message indices
189
+ // Just add events as-is
190
+ allEvents.push(...result.events);
191
+ // Track drift scores
192
+ if (result.drift_score !== undefined) {
193
+ driftScores.push(result.drift_score);
194
+ }
195
+ if (result.usage) {
196
+ totalUsage.promptTokens += result.usage.promptTokens;
197
+ totalUsage.completionTokens += result.usage.completionTokens;
198
+ totalUsage.totalTokens += result.usage.totalTokens;
199
+ }
200
+ }
201
+ // Use max drift score across batches (worst case)
202
+ const drift_score = driftScores.length > 0
203
+ ? Math.max(...driftScores)
204
+ : undefined;
205
+ return {
206
+ events: allEvents,
207
+ drift_score,
208
+ timing_ms: performance.now() - start,
209
+ usage: totalUsage,
210
+ };
211
+ }
212
+ //# sourceMappingURL=detect-llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-llm.js","sourceRoot":"","sources":["../../../src/core/llm/detect-llm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * LLM-based fact extraction
3
+ */
4
+ import { TranscriptMessage, ExtractedFact } from '../types.js';
5
+ import { LLMClient } from './client.js';
6
+ export interface ExtractFactsLLMResult {
7
+ facts: ExtractedFact[];
8
+ timing_ms: number;
9
+ usage?: {
10
+ promptTokens: number;
11
+ completionTokens: number;
12
+ totalTokens: number;
13
+ };
14
+ }
15
+ /**
16
+ * Extract facts from transcript using LLM
17
+ */
18
+ export declare function extractFactsLLM(messages: TranscriptMessage[], llmClient: LLMClient): Promise<ExtractFactsLLMResult>;
19
+ /**
20
+ * Extract facts from raw transcript text using LLM
21
+ */
22
+ export declare function extractFactsLLMFromRaw(rawText: string, llmClient: LLMClient): Promise<ExtractFactsLLMResult>;
23
+ /**
24
+ * Extract facts in batches for large transcripts
25
+ */
26
+ export declare function extractFactsLLMBatched(messages: TranscriptMessage[], llmClient: LLMClient, batchSize?: number): Promise<ExtractFactsLLMResult>;
27
+ //# sourceMappingURL=extract-llm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-llm.d.ts","sourceRoot":"","sources":["../../../src/core/llm/extract-llm.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOxC,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;QACrB,gBAAgB,EAAE,MAAM,CAAC;QACzB,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,qBAAqB,CAAC,CAwEhC;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,qBAAqB,CAAC,CAgDhC;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,SAAS,EAAE,SAAS,EACpB,SAAS,SAAK,GACb,OAAO,CAAC,qBAAqB,CAAC,CA+BhC"}
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ /**
3
+ * LLM-based fact extraction
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.extractFactsLLM = extractFactsLLM;
7
+ exports.extractFactsLLMFromRaw = extractFactsLLMFromRaw;
8
+ exports.extractFactsLLMBatched = extractFactsLLMBatched;
9
+ const prompts_js_1 = require("./prompts.js");
10
+ /**
11
+ * Extract facts from transcript using LLM
12
+ */
13
+ async function extractFactsLLM(messages, llmClient) {
14
+ const start = performance.now();
15
+ // Format messages for the prompt
16
+ const formattedMessages = messages
17
+ .filter(m => m.role === 'user')
18
+ .map(m => `[${m.idx}] ${m.role}: ${m.content}`);
19
+ if (formattedMessages.length === 0) {
20
+ return {
21
+ facts: [],
22
+ timing_ms: performance.now() - start,
23
+ };
24
+ }
25
+ try {
26
+ // Call LLM
27
+ const prompt = (0, prompts_js_1.createFactExtractionPrompt)(formattedMessages);
28
+ const response = await llmClient.complete(prompt, prompts_js_1.FACT_EXTRACTION_SYSTEM);
29
+ // Parse and validate response
30
+ let llmResponse;
31
+ try {
32
+ llmResponse = JSON.parse(response.content);
33
+ }
34
+ catch (parseError) {
35
+ throw new Error(`Failed to parse LLM response as JSON: ${parseError.message}\n` +
36
+ `Response content: ${response.content.substring(0, 200)}...`);
37
+ }
38
+ // Validate response structure
39
+ if (!llmResponse || typeof llmResponse !== 'object') {
40
+ throw new Error('LLM response is not a valid object');
41
+ }
42
+ if (!Array.isArray(llmResponse.facts)) {
43
+ throw new Error('LLM response does not contain a facts array');
44
+ }
45
+ const facts = llmResponse.facts;
46
+ // Map message indices from LLM response back to actual indices
47
+ const userMessages = messages.filter(m => m.role === 'user');
48
+ const mappedFacts = facts.map((fact) => {
49
+ // If msg_idx is provided, map it to actual message index
50
+ let actualMsgIdx = 0;
51
+ if (typeof fact.msg_idx === 'number' && fact.msg_idx < userMessages.length) {
52
+ actualMsgIdx = userMessages[fact.msg_idx].idx;
53
+ }
54
+ else {
55
+ // Default to the first user message
56
+ actualMsgIdx = userMessages[0]?.idx || 0;
57
+ }
58
+ return {
59
+ fact_key: fact.fact_key,
60
+ fact_value: fact.fact_value,
61
+ msg_idx: actualMsgIdx,
62
+ confidence: fact.confidence || 0.5,
63
+ };
64
+ });
65
+ return {
66
+ facts: mappedFacts,
67
+ timing_ms: performance.now() - start,
68
+ usage: response.usage,
69
+ };
70
+ }
71
+ catch (error) {
72
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
73
+ throw new Error(`LLM fact extraction failed: ${errorMessage}`);
74
+ }
75
+ }
76
+ /**
77
+ * Extract facts from raw transcript text using LLM
78
+ */
79
+ async function extractFactsLLMFromRaw(rawText, llmClient) {
80
+ const start = performance.now();
81
+ if (!rawText || rawText.trim().length === 0) {
82
+ return {
83
+ facts: [],
84
+ timing_ms: performance.now() - start,
85
+ };
86
+ }
87
+ try {
88
+ const prompt = (0, prompts_js_1.createFactExtractionPromptFromRaw)(rawText);
89
+ const response = await llmClient.complete(prompt, prompts_js_1.FACT_EXTRACTION_SYSTEM);
90
+ let llmResponse;
91
+ try {
92
+ llmResponse = JSON.parse(response.content);
93
+ }
94
+ catch (parseError) {
95
+ throw new Error(`Failed to parse LLM response as JSON: ${parseError.message}\n` +
96
+ `Response content: ${response.content.substring(0, 200)}...`);
97
+ }
98
+ if (!llmResponse || typeof llmResponse !== 'object') {
99
+ throw new Error('LLM response is not a valid object');
100
+ }
101
+ if (!Array.isArray(llmResponse.facts)) {
102
+ throw new Error('LLM response does not contain a facts array');
103
+ }
104
+ const facts = llmResponse.facts.map((fact) => ({
105
+ fact_key: fact.fact_key,
106
+ fact_value: fact.fact_value,
107
+ msg_idx: 0,
108
+ confidence: fact.confidence || 0.5,
109
+ }));
110
+ return {
111
+ facts,
112
+ timing_ms: performance.now() - start,
113
+ usage: response.usage,
114
+ };
115
+ }
116
+ catch (error) {
117
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
118
+ throw new Error(`LLM fact extraction failed: ${errorMessage}`);
119
+ }
120
+ }
121
+ /**
122
+ * Extract facts in batches for large transcripts
123
+ */
124
+ async function extractFactsLLMBatched(messages, llmClient, batchSize = 50) {
125
+ const start = performance.now();
126
+ const allFacts = [];
127
+ let totalUsage = {
128
+ promptTokens: 0,
129
+ completionTokens: 0,
130
+ totalTokens: 0,
131
+ };
132
+ // Filter user messages
133
+ const userMessages = messages.filter(m => m.role === 'user');
134
+ // Process in batches
135
+ for (let i = 0; i < userMessages.length; i += batchSize) {
136
+ const batch = userMessages.slice(i, i + batchSize);
137
+ const result = await extractFactsLLM(batch, llmClient);
138
+ allFacts.push(...result.facts);
139
+ if (result.usage) {
140
+ totalUsage.promptTokens += result.usage.promptTokens;
141
+ totalUsage.completionTokens += result.usage.completionTokens;
142
+ totalUsage.totalTokens += result.usage.totalTokens;
143
+ }
144
+ }
145
+ return {
146
+ facts: allFacts,
147
+ timing_ms: performance.now() - start,
148
+ usage: totalUsage,
149
+ };
150
+ }
151
+ //# sourceMappingURL=extract-llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-llm.js","sourceRoot":"","sources":["../../../src/core/llm/extract-llm.ts"],"names":[],"mappings":"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"}