learngraph 0.2.0 → 0.4.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.
Files changed (76) hide show
  1. package/README.md +82 -1
  2. package/dist/cjs/llm/adapters/anthropic.js +124 -0
  3. package/dist/cjs/llm/adapters/anthropic.js.map +1 -0
  4. package/dist/cjs/llm/adapters/base.js +100 -0
  5. package/dist/cjs/llm/adapters/base.js.map +1 -0
  6. package/dist/cjs/llm/adapters/gemini.js +156 -0
  7. package/dist/cjs/llm/adapters/gemini.js.map +1 -0
  8. package/dist/cjs/llm/adapters/index.js +33 -0
  9. package/dist/cjs/llm/adapters/index.js.map +1 -0
  10. package/dist/cjs/llm/adapters/mediapipe.js +290 -0
  11. package/dist/cjs/llm/adapters/mediapipe.js.map +1 -0
  12. package/dist/cjs/llm/adapters/ollama.js +149 -0
  13. package/dist/cjs/llm/adapters/ollama.js.map +1 -0
  14. package/dist/cjs/llm/adapters/openai.js +126 -0
  15. package/dist/cjs/llm/adapters/openai.js.map +1 -0
  16. package/dist/cjs/llm/adapters/openrouter.js +190 -0
  17. package/dist/cjs/llm/adapters/openrouter.js.map +1 -0
  18. package/dist/cjs/llm/index.js +42 -5
  19. package/dist/cjs/llm/index.js.map +1 -1
  20. package/dist/cjs/llm/orchestrator.js +219 -0
  21. package/dist/cjs/llm/orchestrator.js.map +1 -0
  22. package/dist/cjs/llm/prompts.js +367 -0
  23. package/dist/cjs/llm/prompts.js.map +1 -0
  24. package/dist/cjs/types/llm.js +8 -0
  25. package/dist/cjs/types/llm.js.map +1 -0
  26. package/dist/esm/llm/adapters/anthropic.js +119 -0
  27. package/dist/esm/llm/adapters/anthropic.js.map +1 -0
  28. package/dist/esm/llm/adapters/base.js +95 -0
  29. package/dist/esm/llm/adapters/base.js.map +1 -0
  30. package/dist/esm/llm/adapters/gemini.js +151 -0
  31. package/dist/esm/llm/adapters/gemini.js.map +1 -0
  32. package/dist/esm/llm/adapters/index.js +13 -0
  33. package/dist/esm/llm/adapters/index.js.map +1 -0
  34. package/dist/esm/llm/adapters/mediapipe.js +252 -0
  35. package/dist/esm/llm/adapters/mediapipe.js.map +1 -0
  36. package/dist/esm/llm/adapters/ollama.js +144 -0
  37. package/dist/esm/llm/adapters/ollama.js.map +1 -0
  38. package/dist/esm/llm/adapters/openai.js +121 -0
  39. package/dist/esm/llm/adapters/openai.js.map +1 -0
  40. package/dist/esm/llm/adapters/openrouter.js +185 -0
  41. package/dist/esm/llm/adapters/openrouter.js.map +1 -0
  42. package/dist/esm/llm/index.js +12 -6
  43. package/dist/esm/llm/index.js.map +1 -1
  44. package/dist/esm/llm/orchestrator.js +214 -0
  45. package/dist/esm/llm/orchestrator.js.map +1 -0
  46. package/dist/esm/llm/prompts.js +360 -0
  47. package/dist/esm/llm/prompts.js.map +1 -0
  48. package/dist/esm/types/llm.js +7 -0
  49. package/dist/esm/types/llm.js.map +1 -0
  50. package/dist/types/llm/adapters/anthropic.d.ts +21 -0
  51. package/dist/types/llm/adapters/anthropic.d.ts.map +1 -0
  52. package/dist/types/llm/adapters/base.d.ts +46 -0
  53. package/dist/types/llm/adapters/base.d.ts.map +1 -0
  54. package/dist/types/llm/adapters/gemini.d.ts +30 -0
  55. package/dist/types/llm/adapters/gemini.d.ts.map +1 -0
  56. package/dist/types/llm/adapters/index.d.ts +14 -0
  57. package/dist/types/llm/adapters/index.d.ts.map +1 -0
  58. package/dist/types/llm/adapters/mediapipe.d.ts +113 -0
  59. package/dist/types/llm/adapters/mediapipe.d.ts.map +1 -0
  60. package/dist/types/llm/adapters/ollama.d.ts +30 -0
  61. package/dist/types/llm/adapters/ollama.d.ts.map +1 -0
  62. package/dist/types/llm/adapters/openai.d.ts +22 -0
  63. package/dist/types/llm/adapters/openai.d.ts.map +1 -0
  64. package/dist/types/llm/adapters/openrouter.d.ts +58 -0
  65. package/dist/types/llm/adapters/openrouter.d.ts.map +1 -0
  66. package/dist/types/llm/index.d.ts +5 -0
  67. package/dist/types/llm/index.d.ts.map +1 -1
  68. package/dist/types/llm/orchestrator.d.ts +35 -0
  69. package/dist/types/llm/orchestrator.d.ts.map +1 -0
  70. package/dist/types/llm/prompts.d.ts +269 -0
  71. package/dist/types/llm/prompts.d.ts.map +1 -0
  72. package/dist/types/types/index.d.ts +1 -0
  73. package/dist/types/types/index.d.ts.map +1 -1
  74. package/dist/types/types/llm.d.ts +337 -0
  75. package/dist/types/types/llm.d.ts.map +1 -0
  76. package/package.json +6 -2
@@ -0,0 +1,121 @@
1
+ /**
2
+ * OpenAI adapter for LLM integration
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ import { BaseLLMAdapter, LLMError, DEFAULT_CONFIG } from './base.js';
7
+ /**
8
+ * OpenAI adapter for chat completions
9
+ */
10
+ export class OpenAIAdapter extends BaseLLMAdapter {
11
+ baseUrl;
12
+ organization;
13
+ constructor(config) {
14
+ super(config);
15
+ this.baseUrl = config.baseUrl ?? 'https://api.openai.com/v1';
16
+ if (config.organization) {
17
+ this.organization = config.organization;
18
+ }
19
+ }
20
+ get provider() {
21
+ return 'openai';
22
+ }
23
+ async complete(request) {
24
+ if (!this.isConfigured()) {
25
+ throw new LLMError('OpenAI adapter not configured. Set OPENAI_API_KEY or pass apiKey in config.', 'NOT_CONFIGURED', this.provider);
26
+ }
27
+ return this.withRetry(async () => {
28
+ const headers = {
29
+ 'Content-Type': 'application/json',
30
+ Authorization: `Bearer ${this.config.apiKey}`,
31
+ };
32
+ if (this.organization) {
33
+ headers['OpenAI-Organization'] = this.organization;
34
+ }
35
+ const body = {
36
+ model: this.config.model,
37
+ messages: request.messages.map((m) => ({
38
+ role: m.role,
39
+ content: m.content,
40
+ })),
41
+ max_tokens: request.maxTokens ?? this.config.maxTokens ?? DEFAULT_CONFIG.maxTokens,
42
+ temperature: request.temperature ?? this.config.temperature ?? DEFAULT_CONFIG.temperature,
43
+ };
44
+ // Add JSON mode if requested
45
+ if (request.responseFormat === 'json') {
46
+ body.response_format = { type: 'json_object' };
47
+ }
48
+ const controller = new AbortController();
49
+ const timeout = setTimeout(() => controller.abort(), this.config.timeout ?? DEFAULT_CONFIG.timeout);
50
+ try {
51
+ const response = await fetch(`${this.baseUrl}/chat/completions`, {
52
+ method: 'POST',
53
+ headers,
54
+ body: JSON.stringify(body),
55
+ signal: controller.signal,
56
+ });
57
+ clearTimeout(timeout);
58
+ if (!response.ok) {
59
+ const errorData = (await response.json().catch(() => ({})));
60
+ const errorMessage = errorData.error?.message ?? `HTTP ${response.status}`;
61
+ if (response.status === 429) {
62
+ throw new LLMError(`Rate limit exceeded: ${errorMessage}`, 'RATE_LIMIT', this.provider);
63
+ }
64
+ throw new LLMError(`OpenAI API error: ${errorMessage}`, 'API_ERROR', this.provider);
65
+ }
66
+ const data = (await response.json());
67
+ const choice = data.choices[0];
68
+ if (!choice) {
69
+ throw new LLMError('No response from OpenAI', 'INVALID_RESPONSE', this.provider);
70
+ }
71
+ const content = choice.message.content;
72
+ let json;
73
+ if (request.responseFormat === 'json') {
74
+ json = this.parseJSON(content);
75
+ }
76
+ return {
77
+ content,
78
+ json,
79
+ usage: {
80
+ promptTokens: data.usage.prompt_tokens,
81
+ completionTokens: data.usage.completion_tokens,
82
+ totalTokens: data.usage.total_tokens,
83
+ },
84
+ model: data.model,
85
+ finishReason: choice.finish_reason === 'stop' ? 'stop' :
86
+ choice.finish_reason === 'length' ? 'length' :
87
+ choice.finish_reason === 'content_filter' ? 'content_filter' : 'error',
88
+ };
89
+ }
90
+ catch (error) {
91
+ clearTimeout(timeout);
92
+ if (error instanceof LLMError) {
93
+ throw error;
94
+ }
95
+ if (error instanceof Error) {
96
+ if (error.name === 'AbortError') {
97
+ throw new LLMError('Request timeout', 'TIMEOUT', this.provider, error);
98
+ }
99
+ throw new LLMError(`Network error: ${error.message}`, 'NETWORK_ERROR', this.provider, error);
100
+ }
101
+ throw new LLMError('Unknown error', 'API_ERROR', this.provider);
102
+ }
103
+ });
104
+ }
105
+ }
106
+ /**
107
+ * Create an OpenAI adapter from environment variables
108
+ */
109
+ export function createOpenAIAdapter(model = 'gpt-4o', overrides) {
110
+ const apiKey = typeof process !== 'undefined' ? process.env.OPENAI_API_KEY : undefined;
111
+ const config = {
112
+ provider: 'openai',
113
+ model,
114
+ ...overrides,
115
+ };
116
+ if (apiKey) {
117
+ config.apiKey = apiKey;
118
+ }
119
+ return new OpenAIAdapter(config);
120
+ }
121
+ //# sourceMappingURL=openai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../../src/llm/adapters/openai.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * OpenRouter LLM adapter
3
+ *
4
+ * OpenRouter provides access to many models through a single API:
5
+ * - OpenAI (GPT-4, GPT-3.5)
6
+ * - Anthropic (Claude)
7
+ * - Google (Gemini, PaLM)
8
+ * - Meta (Llama)
9
+ * - Mistral
10
+ * - And many more
11
+ *
12
+ * @packageDocumentation
13
+ */
14
+ import { BaseLLMAdapter, LLMError } from './base.js';
15
+ /**
16
+ * Popular models available on OpenRouter
17
+ */
18
+ export const OPENROUTER_MODELS = {
19
+ // OpenAI
20
+ 'openai/gpt-4o': 'openai/gpt-4o',
21
+ 'openai/gpt-4-turbo': 'openai/gpt-4-turbo',
22
+ 'openai/gpt-3.5-turbo': 'openai/gpt-3.5-turbo',
23
+ // Anthropic
24
+ 'anthropic/claude-3.5-sonnet': 'anthropic/claude-3.5-sonnet',
25
+ 'anthropic/claude-3-opus': 'anthropic/claude-3-opus',
26
+ 'anthropic/claude-3-haiku': 'anthropic/claude-3-haiku',
27
+ // Google
28
+ 'google/gemini-pro': 'google/gemini-pro',
29
+ 'google/gemini-pro-1.5': 'google/gemini-pro-1.5',
30
+ // Meta
31
+ 'meta-llama/llama-3.1-70b-instruct': 'meta-llama/llama-3.1-70b-instruct',
32
+ 'meta-llama/llama-3.1-8b-instruct': 'meta-llama/llama-3.1-8b-instruct',
33
+ // Mistral
34
+ 'mistralai/mistral-large': 'mistralai/mistral-large',
35
+ 'mistralai/mistral-medium': 'mistralai/mistral-medium',
36
+ 'mistralai/mixtral-8x7b-instruct': 'mistralai/mixtral-8x7b-instruct',
37
+ // DeepSeek
38
+ 'deepseek/deepseek-chat': 'deepseek/deepseek-chat',
39
+ 'deepseek/deepseek-coder': 'deepseek/deepseek-coder',
40
+ // Qwen
41
+ 'qwen/qwen-2.5-72b-instruct': 'qwen/qwen-2.5-72b-instruct',
42
+ };
43
+ /**
44
+ * Adapter for OpenRouter API
45
+ *
46
+ * OpenRouter provides unified access to 100+ models from various providers.
47
+ * See https://openrouter.ai/docs for full documentation.
48
+ */
49
+ export class OpenRouterAdapter extends BaseLLMAdapter {
50
+ baseUrl;
51
+ siteUrl;
52
+ appName;
53
+ constructor(config) {
54
+ super(config);
55
+ this.baseUrl = config.baseUrl ?? 'https://openrouter.ai/api/v1';
56
+ if (config.siteUrl) {
57
+ this.siteUrl = config.siteUrl;
58
+ }
59
+ if (config.appName) {
60
+ this.appName = config.appName;
61
+ }
62
+ }
63
+ get provider() {
64
+ return 'openrouter';
65
+ }
66
+ async complete(request) {
67
+ if (!this.isConfigured()) {
68
+ throw new LLMError('OpenRouter adapter is not configured. Set OPENROUTER_API_KEY environment variable.', 'NOT_CONFIGURED', this.provider);
69
+ }
70
+ const openRouterRequest = this.buildRequest(request);
71
+ try {
72
+ const response = await this.executeRequest(openRouterRequest);
73
+ return this.parseResponse(response);
74
+ }
75
+ catch (error) {
76
+ if (error instanceof LLMError) {
77
+ throw error;
78
+ }
79
+ throw new LLMError(`OpenRouter API request failed: ${error instanceof Error ? error.message : 'Unknown error'}`, 'API_ERROR', this.provider, error instanceof Error ? error : undefined);
80
+ }
81
+ }
82
+ buildRequest(request) {
83
+ const openRouterRequest = {
84
+ model: this.config.model,
85
+ messages: request.messages.map((m) => ({
86
+ role: m.role,
87
+ content: m.content,
88
+ })),
89
+ max_tokens: request.maxTokens ?? this.config.maxTokens ?? 4096,
90
+ temperature: request.temperature ?? this.config.temperature ?? 0.3,
91
+ };
92
+ // Handle JSON response format
93
+ if (request.responseFormat === 'json') {
94
+ openRouterRequest.response_format = { type: 'json_object' };
95
+ }
96
+ return openRouterRequest;
97
+ }
98
+ async executeRequest(request) {
99
+ const headers = {
100
+ 'Content-Type': 'application/json',
101
+ Authorization: `Bearer ${this.config.apiKey}`,
102
+ };
103
+ // Add optional OpenRouter-specific headers for rankings
104
+ if (this.siteUrl) {
105
+ headers['HTTP-Referer'] = this.siteUrl;
106
+ }
107
+ if (this.appName) {
108
+ headers['X-Title'] = this.appName;
109
+ }
110
+ const response = await fetch(`${this.baseUrl}/chat/completions`, {
111
+ method: 'POST',
112
+ headers,
113
+ body: JSON.stringify(request),
114
+ signal: AbortSignal.timeout(this.config.timeout ?? 60000),
115
+ });
116
+ if (!response.ok) {
117
+ const errorBody = await response.text();
118
+ let errorMessage = `HTTP ${response.status}`;
119
+ try {
120
+ const errorJson = JSON.parse(errorBody);
121
+ errorMessage = errorJson.error?.message ?? errorMessage;
122
+ }
123
+ catch {
124
+ errorMessage = errorBody || errorMessage;
125
+ }
126
+ if (response.status === 429) {
127
+ throw new LLMError(`Rate limit exceeded: ${errorMessage}`, 'RATE_LIMIT', this.provider);
128
+ }
129
+ if (response.status === 402) {
130
+ throw new LLMError(`Payment required or insufficient credits: ${errorMessage}`, 'API_ERROR', this.provider);
131
+ }
132
+ throw new LLMError(`OpenRouter API error: ${errorMessage}`, 'API_ERROR', this.provider);
133
+ }
134
+ return response.json();
135
+ }
136
+ parseResponse(response) {
137
+ if (!response.choices || response.choices.length === 0) {
138
+ throw new LLMError('No choices in OpenRouter response', 'INVALID_RESPONSE', this.provider);
139
+ }
140
+ const choice = response.choices[0];
141
+ if (!choice) {
142
+ throw new LLMError('No choice in OpenRouter response', 'INVALID_RESPONSE', this.provider);
143
+ }
144
+ const content = choice.message.content;
145
+ // Try to parse JSON if present
146
+ let json;
147
+ try {
148
+ json = this.parseJSON(content);
149
+ }
150
+ catch {
151
+ // Not JSON, that's fine
152
+ }
153
+ // Map finish reasons to our standard format
154
+ const finishReason = choice.finish_reason === 'stop' ? 'stop' :
155
+ choice.finish_reason === 'length' ? 'length' :
156
+ choice.finish_reason === 'content_filter' ? 'content_filter' : 'stop';
157
+ return {
158
+ content,
159
+ json,
160
+ usage: {
161
+ promptTokens: response.usage.prompt_tokens,
162
+ completionTokens: response.usage.completion_tokens,
163
+ totalTokens: response.usage.total_tokens,
164
+ },
165
+ model: response.model,
166
+ finishReason,
167
+ };
168
+ }
169
+ }
170
+ /**
171
+ * Create an OpenRouter adapter from environment variables
172
+ */
173
+ export function createOpenRouterAdapter(model = 'anthropic/claude-3.5-sonnet', overrides) {
174
+ const apiKey = typeof process !== 'undefined' ? process.env.OPENROUTER_API_KEY : undefined;
175
+ const config = {
176
+ provider: 'openrouter',
177
+ model,
178
+ ...overrides,
179
+ };
180
+ if (apiKey) {
181
+ config.apiKey = apiKey;
182
+ }
183
+ return new OpenRouterAdapter(config);
184
+ }
185
+ //# sourceMappingURL=openrouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../../../../src/llm/adapters/openrouter.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,18 @@
1
- "use strict";
2
1
  /**
3
2
  * LLM integration for skill extraction and prerequisite inference
4
3
  *
5
4
  * @packageDocumentation
6
5
  */
7
- // LLM integration will be implemented in Phase 4
8
- // export { LLMOrchestrator } from './orchestrator.js';
9
- // export { OpenAIAdapter } from './adapters/openai.js';
10
- // export { AnthropicAdapter } from './adapters/anthropic.js';
11
- // export { OllamaAdapter } from './adapters/ollama.js';
6
+ // ─────────────────────────────────────────────────────────────────────────────
7
+ // Adapters
8
+ // ─────────────────────────────────────────────────────────────────────────────
9
+ export { BaseLLMAdapter, LLMError, DEFAULT_CONFIG, OpenAIAdapter, createOpenAIAdapter, AnthropicAdapter, createAnthropicAdapter, OllamaAdapter, createOllamaAdapter, GeminiAdapter, createGeminiAdapter, OpenRouterAdapter, createOpenRouterAdapter, OPENROUTER_MODELS, MediaPipeAdapter, createMediaPipeAdapter, MEDIAPIPE_MODELS, } from './adapters/index.js';
10
+ // ─────────────────────────────────────────────────────────────────────────────
11
+ // Orchestrator
12
+ // ─────────────────────────────────────────────────────────────────────────────
13
+ export { LLMOrchestrator, createOrchestrator } from './orchestrator.js';
14
+ // ─────────────────────────────────────────────────────────────────────────────
15
+ // Prompts
16
+ // ─────────────────────────────────────────────────────────────────────────────
17
+ export { SYSTEM_PROMPTS, EXTRACTION_SCHEMA, PREREQUISITE_SCHEMA, BLOOM_ANALYSIS_SCHEMA, DECOMPOSITION_SCHEMA, buildExtractionPrompt, buildPrerequisitePrompt, buildBloomPrompt, buildDecompositionPrompt, } from './prompts.js';
12
18
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/llm/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;AAEH,iDAAiD;AACjD,uDAAuD;AACvD,wDAAwD;AACxD,8DAA8D;AAC9D,wDAAwD"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/llm/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAgCH,gFAAgF;AAChF,WAAW;AACX,gFAAgF;AAChF,OAAO,EACL,cAAc,EACd,QAAQ,EACR,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,gBAAgB,EAChB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,GACjB,MAAM,qBAAqB,CAAC;AAG7B,gFAAgF;AAChF,eAAe;AACf,gFAAgF;AAChF,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAExE,gFAAgF;AAChF,UAAU;AACV,gFAAgF;AAChF,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,214 @@
1
+ /**
2
+ * LLM orchestrator for educational tasks
3
+ *
4
+ * @packageDocumentation
5
+ */
6
+ import { SKILL_DEFAULTS, THRESHOLD_CONCEPT_MASTERY } from '../types/skill.js';
7
+ import { SYSTEM_PROMPTS, EXTRACTION_SCHEMA, PREREQUISITE_SCHEMA, BLOOM_ANALYSIS_SCHEMA, DECOMPOSITION_SCHEMA, buildExtractionPrompt, buildPrerequisitePrompt, buildBloomPrompt, buildDecompositionPrompt, } from './prompts.js';
8
+ /** Default estimated minutes for skill mastery */
9
+ const DEFAULT_ESTIMATED_MINUTES = 30;
10
+ /**
11
+ * Difficulty mapping for Bloom's levels
12
+ */
13
+ const BLOOM_DIFFICULTY = {
14
+ remember: 0.2,
15
+ understand: 0.35,
16
+ apply: 0.5,
17
+ analyze: 0.65,
18
+ evaluate: 0.8,
19
+ create: 0.9,
20
+ };
21
+ /**
22
+ * High-level orchestrator for LLM-based educational tasks
23
+ */
24
+ export class LLMOrchestrator {
25
+ adapter;
26
+ constructor(adapter) {
27
+ this.adapter = adapter;
28
+ }
29
+ getAdapter() {
30
+ return this.adapter;
31
+ }
32
+ /**
33
+ * Extract skills from curriculum content
34
+ */
35
+ async extractSkills(request) {
36
+ const startTime = Date.now();
37
+ // Build options object conditionally to avoid undefined values
38
+ const extractionOptions = {};
39
+ if (request.domain)
40
+ extractionOptions.domain = request.domain;
41
+ if (request.gradeLevel)
42
+ extractionOptions.gradeLevel = request.gradeLevel;
43
+ if (request.context)
44
+ extractionOptions.context = request.context;
45
+ const messages = [
46
+ { role: 'system', content: SYSTEM_PROMPTS.skillExtraction },
47
+ {
48
+ role: 'user',
49
+ content: buildExtractionPrompt(request.content, extractionOptions),
50
+ },
51
+ ];
52
+ const response = await this.adapter.complete({
53
+ messages,
54
+ responseFormat: 'json',
55
+ jsonSchema: EXTRACTION_SCHEMA,
56
+ });
57
+ const parsed = response.json;
58
+ // Apply filters and defaults
59
+ let skills = parsed.skills.map((skill) => ({
60
+ ...skill,
61
+ isThresholdConcept: skill.isThresholdConcept ?? false,
62
+ confidence: skill.confidence ?? 0.8,
63
+ }));
64
+ // Filter by minimum confidence
65
+ if (request.minConfidence) {
66
+ skills = skills.filter((s) => s.confidence >= request.minConfidence);
67
+ }
68
+ // Calculate overall confidence
69
+ const confidence = skills.length > 0 ? skills.reduce((acc, s) => acc + s.confidence, 0) / skills.length : 0;
70
+ return {
71
+ skills,
72
+ confidence,
73
+ usage: response.usage,
74
+ warnings: parsed.warnings ?? [],
75
+ durationMs: Date.now() - startTime,
76
+ };
77
+ }
78
+ /**
79
+ * Infer prerequisites between skills
80
+ */
81
+ async inferPrerequisites(request) {
82
+ const startTime = Date.now();
83
+ // Build options object conditionally to avoid undefined values
84
+ const prerequisiteOptions = {};
85
+ if (request.domain)
86
+ prerequisiteOptions.domain = request.domain;
87
+ if (request.inferTransitive !== undefined)
88
+ prerequisiteOptions.inferTransitive = request.inferTransitive;
89
+ const messages = [
90
+ { role: 'system', content: SYSTEM_PROMPTS.prerequisiteInference },
91
+ {
92
+ role: 'user',
93
+ content: buildPrerequisitePrompt(request.skills, prerequisiteOptions),
94
+ },
95
+ ];
96
+ const response = await this.adapter.complete({
97
+ messages,
98
+ responseFormat: 'json',
99
+ jsonSchema: PREREQUISITE_SCHEMA,
100
+ });
101
+ const parsed = response.json;
102
+ // Filter by minimum confidence
103
+ let prerequisites = parsed.prerequisites;
104
+ if (request.minConfidence) {
105
+ prerequisites = prerequisites.filter((p) => p.confidence >= request.minConfidence);
106
+ }
107
+ return {
108
+ prerequisites,
109
+ usage: response.usage,
110
+ durationMs: Date.now() - startTime,
111
+ };
112
+ }
113
+ /**
114
+ * Analyze Bloom's level of text
115
+ */
116
+ async analyzeBloomLevel(request) {
117
+ const messages = [
118
+ { role: 'system', content: SYSTEM_PROMPTS.bloomAnalysis },
119
+ { role: 'user', content: buildBloomPrompt(request.text, request.context) },
120
+ ];
121
+ const response = await this.adapter.complete({
122
+ messages,
123
+ responseFormat: 'json',
124
+ jsonSchema: BLOOM_ANALYSIS_SCHEMA,
125
+ });
126
+ const parsed = response.json;
127
+ return {
128
+ level: parsed.level,
129
+ confidence: parsed.confidence,
130
+ indicators: parsed.indicators,
131
+ reasoning: parsed.reasoning,
132
+ usage: response.usage,
133
+ };
134
+ }
135
+ /**
136
+ * Full curriculum decomposition into skill graph
137
+ */
138
+ async decompose(request) {
139
+ const startTime = Date.now();
140
+ // Build options object conditionally to avoid undefined values
141
+ const decompositionOptions = {};
142
+ if (request.title)
143
+ decompositionOptions.title = request.title;
144
+ if (request.domain)
145
+ decompositionOptions.domain = request.domain;
146
+ if (request.gradeLevel)
147
+ decompositionOptions.gradeLevel = request.gradeLevel;
148
+ if (request.context)
149
+ decompositionOptions.context = request.context;
150
+ if (request.maxDepth !== undefined)
151
+ decompositionOptions.maxDepth = request.maxDepth;
152
+ const messages = [
153
+ { role: 'system', content: SYSTEM_PROMPTS.curriculumDecomposition },
154
+ {
155
+ role: 'user',
156
+ content: buildDecompositionPrompt(request.content, decompositionOptions),
157
+ },
158
+ ];
159
+ const response = await this.adapter.complete({
160
+ messages,
161
+ responseFormat: 'json',
162
+ jsonSchema: DECOMPOSITION_SCHEMA,
163
+ maxTokens: 8192, // Decomposition can be verbose
164
+ });
165
+ const parsed = response.json;
166
+ // Convert extracted skills to SkillNodeInput format
167
+ const skillInputs = parsed.skills.map((skill) => ({
168
+ name: skill.name,
169
+ description: skill.description,
170
+ bloomLevel: skill.bloomLevel,
171
+ difficulty: skill.difficulty ?? BLOOM_DIFFICULTY[skill.bloomLevel] ?? 0.5,
172
+ isThresholdConcept: skill.isThresholdConcept ?? false,
173
+ masteryThreshold: skill.isThresholdConcept
174
+ ? THRESHOLD_CONCEPT_MASTERY
175
+ : SKILL_DEFAULTS.masteryThreshold,
176
+ estimatedMinutes: skill.estimatedMinutes ?? DEFAULT_ESTIMATED_MINUTES,
177
+ tags: skill.keywords ?? [],
178
+ metadata: {
179
+ llmExtracted: true,
180
+ llmId: skill.id,
181
+ confidence: skill.confidence ?? 0.8,
182
+ },
183
+ }));
184
+ // Convert prerequisites with confidence
185
+ const prerequisites = parsed.prerequisites.map((p) => ({
186
+ sourceId: p.sourceId,
187
+ targetId: p.targetId,
188
+ strength: p.strength,
189
+ type: p.type,
190
+ confidence: 0.8, // Default confidence for decomposition
191
+ reasoning: p.reasoning ?? 'Inferred from curriculum structure',
192
+ }));
193
+ return {
194
+ title: parsed.title || request.title || 'Untitled Curriculum',
195
+ skills: parsed.skills.map((s) => ({
196
+ ...s,
197
+ isThresholdConcept: s.isThresholdConcept ?? false,
198
+ confidence: s.confidence ?? 0.8,
199
+ })),
200
+ prerequisites,
201
+ skillInputs,
202
+ usage: response.usage,
203
+ durationMs: Date.now() - startTime,
204
+ warnings: parsed.warnings ?? [],
205
+ };
206
+ }
207
+ }
208
+ /**
209
+ * Create an orchestrator with a specific adapter
210
+ */
211
+ export function createOrchestrator(adapter) {
212
+ return new LLMOrchestrator(adapter);
213
+ }
214
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../../src/llm/orchestrator.ts"],"names":[],"mappings":"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"}