milwright commited on
Commit
25876df
·
1 Parent(s): 7d032f3

fix: restore tool-calling chat prompt engineering

Browse files

- Update generateContextualHint to use tool-calling architecture instead of basic prompts
- Implement structured responses with focused question type tools
- Add proper tool choice enforcement and response parsing
- Maintain fallback handling for robust operation

Files changed (1) hide show
  1. src/aiService.js +94 -11
src/aiService.js CHANGED
@@ -3,6 +3,54 @@ class OpenRouterService {
3
  this.apiUrl = 'https://openrouter.ai/api/v1/chat/completions';
4
  this.apiKey = this.getApiKey();
5
  this.model = 'google/gemma-3-27b-it:free';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  }
7
 
8
  getApiKey() {
@@ -32,12 +80,22 @@ class OpenRouterService {
32
  }
33
 
34
  try {
35
- const prompts = {
36
- part_of_speech: `What part of speech is the word "${word}" in this sentence: "${sentence}"? Provide a clear, direct answer.`,
37
- sentence_role: `What grammatical role does "${word}" play in this sentence: "${sentence}"? Focus on its function.`,
38
- word_category: `Is "${word}" an abstract or concrete noun? Explain briefly with an example.`,
39
- synonym: `What's a good synonym for "${word}" that would fit in this sentence: "${sentence}"?`
40
- };
 
 
 
 
 
 
 
 
 
 
41
 
42
  const response = await fetch(this.apiUrl, {
43
  method: 'POST',
@@ -51,13 +109,21 @@ class OpenRouterService {
51
  model: this.model,
52
  messages: [{
53
  role: 'system',
54
- content: 'You are a helpful reading tutor. Provide clear, educational answers that help students learn without giving away the answer directly.'
55
  }, {
56
  role: 'user',
57
- content: prompts[questionType] || `Help me understand the word "${word}" in this context: "${sentence}"`
58
  }],
59
- max_tokens: 150,
60
- temperature: 0.7
 
 
 
 
 
 
 
 
61
  })
62
  });
63
 
@@ -66,7 +132,24 @@ class OpenRouterService {
66
  }
67
 
68
  const data = await response.json();
69
- return data.choices[0].message.content.trim();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  } catch (error) {
71
  console.error('Error generating contextual hint:', error);
72
  return this.getEnhancedFallback(questionType, word, sentence, bookTitle);
 
3
  this.apiUrl = 'https://openrouter.ai/api/v1/chat/completions';
4
  this.apiKey = this.getApiKey();
5
  this.model = 'google/gemma-3-27b-it:free';
6
+
7
+ // Focused tool definitions for specific, non-overlapping question types
8
+ this.questionTools = {
9
+ part_of_speech: {
10
+ name: 'identify_part_of_speech',
11
+ description: 'Identify the grammatical category directly and clearly',
12
+ parameters: {
13
+ type: 'object',
14
+ properties: {
15
+ hint: { type: 'string', description: 'Direct answer: "This is a [noun/verb/adjective/adverb]" then add a simple, concrete clue about what type (e.g., "a thing", "an action", "describes something")' }
16
+ },
17
+ required: ['hint']
18
+ }
19
+ },
20
+ sentence_role: {
21
+ name: 'explain_sentence_role',
22
+ description: 'Explain the structural function using context clues',
23
+ parameters: {
24
+ type: 'object',
25
+ properties: {
26
+ hint: { type: 'string', description: 'Point to specific words around the blank. Example: "Look at \'the whole ___ consisting of\' - what could contain something?" Focus on the immediate context.' }
27
+ },
28
+ required: ['hint']
29
+ }
30
+ },
31
+ word_category: {
32
+ name: 'categorize_word',
33
+ description: 'State clearly if abstract or concrete',
34
+ parameters: {
35
+ type: 'object',
36
+ properties: {
37
+ hint: { type: 'string', description: 'Start simple: "This is abstract/concrete." Then give a relatable example or size clue: "Think about something very big/small" or "Like feelings/objects"' }
38
+ },
39
+ required: ['hint']
40
+ }
41
+ },
42
+ synonym: {
43
+ name: 'provide_synonym',
44
+ description: 'Give clear synonym or similar word',
45
+ parameters: {
46
+ type: 'object',
47
+ properties: {
48
+ hint: { type: 'string', description: 'Direct synonyms or word families: "Try a word similar to [related word]" or "Think of another word for [meaning]"' }
49
+ },
50
+ required: ['hint']
51
+ }
52
+ }
53
+ };
54
  }
55
 
56
  getApiKey() {
 
80
  }
81
 
82
  try {
83
+ // Get the appropriate tool for this question type
84
+ const tool = this.questionTools[questionType];
85
+ if (!tool) {
86
+ console.warn(`Unknown question type: ${questionType}`);
87
+ return this.getEnhancedFallback(questionType, word, sentence, bookTitle);
88
+ }
89
+
90
+ // Create sophisticated tool-calling prompt
91
+ const systemPrompt = `You are an educational reading tutor using structured responses. You must respond using the provided tool to give focused, helpful hints without revealing the answer directly.
92
+
93
+ Context: This is from "${bookTitle}" - classic literature requiring thoughtful analysis.
94
+
95
+ Current word to help with: "${word}"
96
+ Sentence context: "${sentence}"
97
+
98
+ Use the ${tool.name} tool to provide an appropriate educational hint.`;
99
 
100
  const response = await fetch(this.apiUrl, {
101
  method: 'POST',
 
109
  model: this.model,
110
  messages: [{
111
  role: 'system',
112
+ content: systemPrompt
113
  }, {
114
  role: 'user',
115
+ content: `Help me understand the word that fits in this context using the ${tool.name} tool.`
116
  }],
117
+ tools: [{
118
+ type: 'function',
119
+ function: tool
120
+ }],
121
+ tool_choice: {
122
+ type: 'function',
123
+ function: { name: tool.name }
124
+ },
125
+ max_tokens: 200,
126
+ temperature: 0.3
127
  })
128
  });
129
 
 
132
  }
133
 
134
  const data = await response.json();
135
+
136
+ // Extract tool call response
137
+ const message = data.choices[0].message;
138
+ if (message.tool_calls && message.tool_calls.length > 0) {
139
+ const toolCall = message.tool_calls[0];
140
+ if (toolCall.function && toolCall.function.arguments) {
141
+ try {
142
+ const args = JSON.parse(toolCall.function.arguments);
143
+ return args.hint || this.getEnhancedFallback(questionType, word, sentence, bookTitle);
144
+ } catch (parseError) {
145
+ console.warn('Failed to parse tool call arguments:', parseError);
146
+ }
147
+ }
148
+ }
149
+
150
+ // Fallback to message content if tool call failed
151
+ return message.content?.trim() || this.getEnhancedFallback(questionType, word, sentence, bookTitle);
152
+
153
  } catch (error) {
154
  console.error('Error generating contextual hint:', error);
155
  return this.getEnhancedFallback(questionType, word, sentence, bookTitle);