universal-llm-client 4.2.0 → 4.5.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 +142 -103
- package/LICENSE +21 -21
- package/README.md +640 -591
- package/dist/ai-model.d.ts +12 -1
- package/dist/ai-model.d.ts.map +1 -1
- package/dist/ai-model.js +36 -1
- package/dist/ai-model.js.map +1 -1
- package/dist/gemma-channel.d.ts +14 -0
- package/dist/gemma-channel.d.ts.map +1 -0
- package/dist/gemma-channel.js +38 -0
- package/dist/gemma-channel.js.map +1 -0
- package/dist/gemma-diffusion.d.ts +49 -0
- package/dist/gemma-diffusion.d.ts.map +1 -0
- package/dist/gemma-diffusion.js +147 -0
- package/dist/gemma-diffusion.js.map +1 -0
- package/dist/http.d.ts +4 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +14 -1
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +183 -7
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +28 -3
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/google.d.ts +22 -1
- package/dist/providers/google.d.ts.map +1 -1
- package/dist/providers/google.js +225 -13
- package/dist/providers/google.js.map +1 -1
- package/dist/providers/ollama.d.ts +2 -0
- package/dist/providers/ollama.d.ts.map +1 -1
- package/dist/providers/ollama.js +59 -30
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/openai.d.ts +14 -0
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +200 -22
- package/dist/providers/openai.js.map +1 -1
- package/dist/router.d.ts +2 -0
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +4 -0
- package/dist/router.js.map +1 -1
- package/dist/stream-decoder.d.ts +12 -0
- package/dist/stream-decoder.d.ts.map +1 -1
- package/dist/stream-decoder.js +182 -5
- package/dist/stream-decoder.js.map +1 -1
- package/dist/thinking.d.ts +36 -0
- package/dist/thinking.d.ts.map +1 -0
- package/dist/thinking.js +52 -0
- package/dist/thinking.js.map +1 -0
- package/package.json +118 -116
- package/src/ai-model.ts +400 -350
- package/src/auditor.ts +213 -213
- package/src/client.ts +402 -402
- package/src/debug/debug-google-streaming.ts +1 -1
- package/src/demos/basic/universal-llm-examples.ts +3 -3
- package/src/demos/diffusion-gemma/.env +29 -0
- package/src/demos/diffusion-gemma/.env.example +27 -0
- package/src/demos/diffusion-gemma/CLAUDE.md +95 -0
- package/src/demos/diffusion-gemma/README.md +59 -0
- package/src/demos/diffusion-gemma/canvas.ts +1606 -0
- package/src/demos/diffusion-gemma/docker-compose.yml +29 -0
- package/src/demos/diffusion-gemma/probe-stream.ts +51 -0
- package/src/demos/diffusion-gemma/probe-tools.ts +55 -0
- package/src/demos/diffusion-gemma/server.ts +1205 -0
- package/src/demos/diffusion-gemma/start-vllm.sh +98 -0
- package/src/gemma-channel.ts +47 -0
- package/src/gemma-diffusion.ts +167 -0
- package/src/http.ts +261 -247
- package/src/index.ts +180 -161
- package/src/interfaces.ts +843 -657
- package/src/mcp.ts +345 -345
- package/src/providers/anthropic.ts +796 -762
- package/src/providers/google.ts +840 -620
- package/src/providers/index.ts +8 -8
- package/src/providers/ollama.ts +503 -469
- package/src/providers/openai.ts +587 -392
- package/src/router.ts +785 -780
- package/src/stream-decoder.ts +535 -361
- package/src/structured-output.ts +759 -759
- package/src/test-scripts/test-google-deep-research.ts +33 -0
- package/src/test-scripts/test-google-streaming-enhanced.ts +147 -147
- package/src/test-scripts/test-google-streaming.ts +1 -1
- package/src/test-scripts/test-google-system-prompt-comprehensive.ts +189 -189
- package/src/test-scripts/test-google-thinking.ts +46 -0
- package/src/test-scripts/test-system-message-positions.ts +163 -163
- package/src/test-scripts/test-system-prompt-improvement-demo.ts +83 -83
- package/src/test-scripts/test-vllm-qwen36.ts +256 -0
- package/src/tests/ai-model.test.ts +1614 -1614
- package/src/tests/auditor.test.ts +224 -224
- package/src/tests/gemma-diffusion.test.ts +115 -0
- package/src/tests/http.test.ts +200 -200
- package/src/tests/interfaces.test.ts +117 -117
- package/src/tests/providers/anthropic.test.ts +118 -0
- package/src/tests/providers/google.test.ts +841 -660
- package/src/tests/providers/ollama.test.ts +1034 -954
- package/src/tests/providers/openai.test.ts +1511 -1122
- package/src/tests/router.test.ts +254 -254
- package/src/tests/stream-decoder.test.ts +263 -179
- package/src/tests/structured-output.test.ts +1450 -1450
- package/src/tests/thinking.test.ts +65 -0
- package/src/tests/tools.test.ts +175 -175
- package/src/thinking.ts +73 -0
- package/src/tools.ts +246 -246
- package/src/zod-adapter.ts +72 -72
|
@@ -1,189 +1,189 @@
|
|
|
1
|
-
import { AIModelFactory } from "../factory";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Comprehensive test for Google models with proper system prompt handling
|
|
5
|
-
* Tests both Gemini (systemInstruction) and Gemma (embedded in user prompt) approaches
|
|
6
|
-
*/
|
|
7
|
-
async function testGoogleSystemPromptHandling() {
|
|
8
|
-
console.log('🧪 Testing Google Models with Proper System Prompt Handling...\n');
|
|
9
|
-
|
|
10
|
-
// Test models with different system instruction approaches
|
|
11
|
-
const models = [
|
|
12
|
-
{
|
|
13
|
-
name: 'Gemini 2.5 Flash Lite',
|
|
14
|
-
model: 'gemini-2.5-flash-lite',
|
|
15
|
-
supportsSystemInstruction: true,
|
|
16
|
-
approach: 'Uses Google systemInstruction parameter'
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
name: 'Gemma 3 27B IT',
|
|
20
|
-
model: 'gemma-3-27b-it',
|
|
21
|
-
supportsSystemInstruction: false,
|
|
22
|
-
approach: 'Embeds system prompt in user message'
|
|
23
|
-
}
|
|
24
|
-
];
|
|
25
|
-
|
|
26
|
-
let allTestsPassed = true;
|
|
27
|
-
|
|
28
|
-
for (const modelInfo of models) {
|
|
29
|
-
console.log(`\n🔬 Testing ${modelInfo.name} (${modelInfo.model})`);
|
|
30
|
-
console.log(`System approach: ${modelInfo.approach}`);
|
|
31
|
-
console.log(`System instruction parameter: ${modelInfo.supportsSystemInstruction ? '✅' : '❌'}`);
|
|
32
|
-
console.log('='.repeat(70));
|
|
33
|
-
|
|
34
|
-
const googleModel = AIModelFactory.createGoogleChatModel(
|
|
35
|
-
modelInfo.model,
|
|
36
|
-
'
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
const testResult = await testModelSystemPrompt(googleModel, modelInfo);
|
|
40
|
-
if (!testResult) {
|
|
41
|
-
allTestsPassed = false;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
return { success: allTestsPassed };
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async function testModelSystemPrompt(googleModel: any, modelInfo: any) {
|
|
49
|
-
const modelName = modelInfo.name;
|
|
50
|
-
let testsPassed = true;
|
|
51
|
-
|
|
52
|
-
// Test 1: Basic functionality without system prompt
|
|
53
|
-
console.log(`\n--- Test 1: Basic Chat (${modelName}) ---`);
|
|
54
|
-
try {
|
|
55
|
-
console.log('Question: "What is 2+2?"');
|
|
56
|
-
|
|
57
|
-
const basicResponse = await googleModel.chat([
|
|
58
|
-
{ role: 'user', content: 'What is 2+2?' }
|
|
59
|
-
]);
|
|
60
|
-
|
|
61
|
-
console.log('Response:', basicResponse.message.content);
|
|
62
|
-
console.log('✅ Basic chat works');
|
|
63
|
-
|
|
64
|
-
} catch (error) {
|
|
65
|
-
console.error(`❌ Basic chat failed for ${modelName}:`, error);
|
|
66
|
-
testsPassed = false;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Test 2: System prompt with math personality
|
|
70
|
-
console.log(`\n--- Test 2: System Prompt - Math Teacher (${modelName}) ---`);
|
|
71
|
-
try {
|
|
72
|
-
console.log('System: "You are a math teacher. Always explain your answers step by step."');
|
|
73
|
-
console.log('Question: "What is 2+2?"');
|
|
74
|
-
|
|
75
|
-
const mathResponse = await googleModel.chat([
|
|
76
|
-
{ role: 'system', content: 'You are a math teacher. Always explain your answers step by step.' },
|
|
77
|
-
{ role: 'user', content: 'What is 2+2?' }
|
|
78
|
-
]);
|
|
79
|
-
|
|
80
|
-
console.log('Response:', mathResponse.message.content);
|
|
81
|
-
|
|
82
|
-
// Check if response is more detailed (indicating system prompt worked)
|
|
83
|
-
const isDetailed = mathResponse.message.content.length > 10 &&
|
|
84
|
-
(mathResponse.message.content.toLowerCase().includes('step') ||
|
|
85
|
-
mathResponse.message.content.toLowerCase().includes('add') ||
|
|
86
|
-
mathResponse.message.content.toLowerCase().includes('plus'));
|
|
87
|
-
|
|
88
|
-
if (isDetailed) {
|
|
89
|
-
console.log('✅ System prompt appears to be working - detailed explanation provided');
|
|
90
|
-
} else {
|
|
91
|
-
console.log('⚠️ System prompt effectiveness unclear - response:', mathResponse.message.content);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
} catch (error) {
|
|
95
|
-
console.error(`❌ Math teacher system prompt failed for ${modelName}:`, error);
|
|
96
|
-
testsPassed = false;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Test 3: System prompt with personality change - streaming
|
|
100
|
-
console.log(`\n--- Test 3: System Prompt Streaming - Pirate (${modelName}) ---`);
|
|
101
|
-
try {
|
|
102
|
-
console.log('System: "You are a friendly pirate. Always use pirate language with Arrr!"');
|
|
103
|
-
console.log('Question: "Count from 1 to 3"');
|
|
104
|
-
console.log('Streaming response:');
|
|
105
|
-
console.log('---');
|
|
106
|
-
|
|
107
|
-
const pirateStream = googleModel.chatStream([
|
|
108
|
-
{ role: 'system', content: 'You are a friendly pirate. Always use pirate language with Arrr!' },
|
|
109
|
-
{ role: 'user', content: 'Count from 1 to 3' }
|
|
110
|
-
]);
|
|
111
|
-
|
|
112
|
-
let streamResponse = '';
|
|
113
|
-
for await (const chunk of pirateStream) {
|
|
114
|
-
process.stdout.write(chunk);
|
|
115
|
-
streamResponse += chunk;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
console.log('\n---');
|
|
119
|
-
|
|
120
|
-
// Check for pirate language
|
|
121
|
-
const hasPirateLanguage = streamResponse.toLowerCase().includes('arr') ||
|
|
122
|
-
streamResponse.toLowerCase().includes('matey') ||
|
|
123
|
-
streamResponse.toLowerCase().includes('ahoy') ||
|
|
124
|
-
streamResponse.toLowerCase().includes('pirate');
|
|
125
|
-
|
|
126
|
-
if (hasPirateLanguage) {
|
|
127
|
-
console.log('✅ System prompt streaming works - pirate language detected!');
|
|
128
|
-
} else {
|
|
129
|
-
console.log('⚠️ System prompt streaming effectiveness unclear');
|
|
130
|
-
console.log('Response was:', streamResponse);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
} catch (error) {
|
|
134
|
-
console.error(`❌ Pirate system prompt streaming failed for ${modelName}:`, error);
|
|
135
|
-
testsPassed = false;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Test 4: Complex system prompt with multiple instructions
|
|
139
|
-
console.log(`\n--- Test 4: Complex System Prompt (${modelName}) ---`);
|
|
140
|
-
try {
|
|
141
|
-
console.log('System: Complex instructions with format requirements');
|
|
142
|
-
console.log('Question: "List 3 colors"');
|
|
143
|
-
|
|
144
|
-
const complexResponse = await googleModel.chat([
|
|
145
|
-
{ role: 'system', content: 'You are a helpful assistant. Always format your lists with numbers. Always say "Here are" before your list. Keep responses very short.' },
|
|
146
|
-
{ role: 'user', content: 'List 3 colors' }
|
|
147
|
-
]);
|
|
148
|
-
|
|
149
|
-
console.log('Response:', complexResponse.message.content);
|
|
150
|
-
|
|
151
|
-
// Check if formatting instructions were followed
|
|
152
|
-
const hasNumbering = /\d+\.|\d+\)/.test(complexResponse.message.content);
|
|
153
|
-
const hasPrefix = complexResponse.message.content.toLowerCase().includes('here are');
|
|
154
|
-
|
|
155
|
-
console.log(`Numbering detected: ${hasNumbering ? '✅' : '❌'}`);
|
|
156
|
-
console.log(`Prefix detected: ${hasPrefix ? '✅' : '❌'}`);
|
|
157
|
-
|
|
158
|
-
if (hasNumbering || hasPrefix) {
|
|
159
|
-
console.log('✅ Complex system prompt partially effective');
|
|
160
|
-
} else {
|
|
161
|
-
console.log('⚠️ Complex system prompt effectiveness unclear');
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
} catch (error) {
|
|
165
|
-
console.error(`❌ Complex system prompt failed for ${modelName}:`, error);
|
|
166
|
-
testsPassed = false;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
console.log(`\n📊 ${modelName} Tests Summary: ${testsPassed ? '✅ PASSED' : '❌ FAILED'}`);
|
|
170
|
-
return testsPassed;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Run the comprehensive test
|
|
174
|
-
testGoogleSystemPromptHandling().then(result => {
|
|
175
|
-
console.log('\n' + '='.repeat(70));
|
|
176
|
-
if (result.success) {
|
|
177
|
-
console.log('🎉 All tests completed successfully!');
|
|
178
|
-
console.log('\n📋 Summary:');
|
|
179
|
-
console.log('✅ Gemini models: Using systemInstruction parameter');
|
|
180
|
-
console.log('✅ Gemma models: Embedding system prompts in user messages');
|
|
181
|
-
console.log('✅ Both streaming and non-streaming work');
|
|
182
|
-
console.log('✅ Complex system prompts handled correctly');
|
|
183
|
-
} else {
|
|
184
|
-
console.log('💥 Some tests failed - check output above');
|
|
185
|
-
}
|
|
186
|
-
console.log('\n💡 Implementation now follows Google\'s recommendations:');
|
|
187
|
-
console.log(' • Gemini: Uses systemInstruction parameter');
|
|
188
|
-
console.log(' • Gemma: Embeds system instructions in user prompts');
|
|
189
|
-
});
|
|
1
|
+
import { AIModelFactory } from "../factory";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Comprehensive test for Google models with proper system prompt handling
|
|
5
|
+
* Tests both Gemini (systemInstruction) and Gemma (embedded in user prompt) approaches
|
|
6
|
+
*/
|
|
7
|
+
async function testGoogleSystemPromptHandling() {
|
|
8
|
+
console.log('🧪 Testing Google Models with Proper System Prompt Handling...\n');
|
|
9
|
+
|
|
10
|
+
// Test models with different system instruction approaches
|
|
11
|
+
const models = [
|
|
12
|
+
{
|
|
13
|
+
name: 'Gemini 2.5 Flash Lite',
|
|
14
|
+
model: 'gemini-2.5-flash-lite',
|
|
15
|
+
supportsSystemInstruction: true,
|
|
16
|
+
approach: 'Uses Google systemInstruction parameter'
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'Gemma 3 27B IT',
|
|
20
|
+
model: 'gemma-3-27b-it',
|
|
21
|
+
supportsSystemInstruction: false,
|
|
22
|
+
approach: 'Embeds system prompt in user message'
|
|
23
|
+
}
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
let allTestsPassed = true;
|
|
27
|
+
|
|
28
|
+
for (const modelInfo of models) {
|
|
29
|
+
console.log(`\n🔬 Testing ${modelInfo.name} (${modelInfo.model})`);
|
|
30
|
+
console.log(`System approach: ${modelInfo.approach}`);
|
|
31
|
+
console.log(`System instruction parameter: ${modelInfo.supportsSystemInstruction ? '✅' : '❌'}`);
|
|
32
|
+
console.log('='.repeat(70));
|
|
33
|
+
|
|
34
|
+
const googleModel = AIModelFactory.createGoogleChatModel(
|
|
35
|
+
modelInfo.model,
|
|
36
|
+
(process.env.GOOGLE_API_KEY ?? '')
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const testResult = await testModelSystemPrompt(googleModel, modelInfo);
|
|
40
|
+
if (!testResult) {
|
|
41
|
+
allTestsPassed = false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { success: allTestsPassed };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function testModelSystemPrompt(googleModel: any, modelInfo: any) {
|
|
49
|
+
const modelName = modelInfo.name;
|
|
50
|
+
let testsPassed = true;
|
|
51
|
+
|
|
52
|
+
// Test 1: Basic functionality without system prompt
|
|
53
|
+
console.log(`\n--- Test 1: Basic Chat (${modelName}) ---`);
|
|
54
|
+
try {
|
|
55
|
+
console.log('Question: "What is 2+2?"');
|
|
56
|
+
|
|
57
|
+
const basicResponse = await googleModel.chat([
|
|
58
|
+
{ role: 'user', content: 'What is 2+2?' }
|
|
59
|
+
]);
|
|
60
|
+
|
|
61
|
+
console.log('Response:', basicResponse.message.content);
|
|
62
|
+
console.log('✅ Basic chat works');
|
|
63
|
+
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.error(`❌ Basic chat failed for ${modelName}:`, error);
|
|
66
|
+
testsPassed = false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Test 2: System prompt with math personality
|
|
70
|
+
console.log(`\n--- Test 2: System Prompt - Math Teacher (${modelName}) ---`);
|
|
71
|
+
try {
|
|
72
|
+
console.log('System: "You are a math teacher. Always explain your answers step by step."');
|
|
73
|
+
console.log('Question: "What is 2+2?"');
|
|
74
|
+
|
|
75
|
+
const mathResponse = await googleModel.chat([
|
|
76
|
+
{ role: 'system', content: 'You are a math teacher. Always explain your answers step by step.' },
|
|
77
|
+
{ role: 'user', content: 'What is 2+2?' }
|
|
78
|
+
]);
|
|
79
|
+
|
|
80
|
+
console.log('Response:', mathResponse.message.content);
|
|
81
|
+
|
|
82
|
+
// Check if response is more detailed (indicating system prompt worked)
|
|
83
|
+
const isDetailed = mathResponse.message.content.length > 10 &&
|
|
84
|
+
(mathResponse.message.content.toLowerCase().includes('step') ||
|
|
85
|
+
mathResponse.message.content.toLowerCase().includes('add') ||
|
|
86
|
+
mathResponse.message.content.toLowerCase().includes('plus'));
|
|
87
|
+
|
|
88
|
+
if (isDetailed) {
|
|
89
|
+
console.log('✅ System prompt appears to be working - detailed explanation provided');
|
|
90
|
+
} else {
|
|
91
|
+
console.log('⚠️ System prompt effectiveness unclear - response:', mathResponse.message.content);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error(`❌ Math teacher system prompt failed for ${modelName}:`, error);
|
|
96
|
+
testsPassed = false;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Test 3: System prompt with personality change - streaming
|
|
100
|
+
console.log(`\n--- Test 3: System Prompt Streaming - Pirate (${modelName}) ---`);
|
|
101
|
+
try {
|
|
102
|
+
console.log('System: "You are a friendly pirate. Always use pirate language with Arrr!"');
|
|
103
|
+
console.log('Question: "Count from 1 to 3"');
|
|
104
|
+
console.log('Streaming response:');
|
|
105
|
+
console.log('---');
|
|
106
|
+
|
|
107
|
+
const pirateStream = googleModel.chatStream([
|
|
108
|
+
{ role: 'system', content: 'You are a friendly pirate. Always use pirate language with Arrr!' },
|
|
109
|
+
{ role: 'user', content: 'Count from 1 to 3' }
|
|
110
|
+
]);
|
|
111
|
+
|
|
112
|
+
let streamResponse = '';
|
|
113
|
+
for await (const chunk of pirateStream) {
|
|
114
|
+
process.stdout.write(chunk);
|
|
115
|
+
streamResponse += chunk;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log('\n---');
|
|
119
|
+
|
|
120
|
+
// Check for pirate language
|
|
121
|
+
const hasPirateLanguage = streamResponse.toLowerCase().includes('arr') ||
|
|
122
|
+
streamResponse.toLowerCase().includes('matey') ||
|
|
123
|
+
streamResponse.toLowerCase().includes('ahoy') ||
|
|
124
|
+
streamResponse.toLowerCase().includes('pirate');
|
|
125
|
+
|
|
126
|
+
if (hasPirateLanguage) {
|
|
127
|
+
console.log('✅ System prompt streaming works - pirate language detected!');
|
|
128
|
+
} else {
|
|
129
|
+
console.log('⚠️ System prompt streaming effectiveness unclear');
|
|
130
|
+
console.log('Response was:', streamResponse);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
} catch (error) {
|
|
134
|
+
console.error(`❌ Pirate system prompt streaming failed for ${modelName}:`, error);
|
|
135
|
+
testsPassed = false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Test 4: Complex system prompt with multiple instructions
|
|
139
|
+
console.log(`\n--- Test 4: Complex System Prompt (${modelName}) ---`);
|
|
140
|
+
try {
|
|
141
|
+
console.log('System: Complex instructions with format requirements');
|
|
142
|
+
console.log('Question: "List 3 colors"');
|
|
143
|
+
|
|
144
|
+
const complexResponse = await googleModel.chat([
|
|
145
|
+
{ role: 'system', content: 'You are a helpful assistant. Always format your lists with numbers. Always say "Here are" before your list. Keep responses very short.' },
|
|
146
|
+
{ role: 'user', content: 'List 3 colors' }
|
|
147
|
+
]);
|
|
148
|
+
|
|
149
|
+
console.log('Response:', complexResponse.message.content);
|
|
150
|
+
|
|
151
|
+
// Check if formatting instructions were followed
|
|
152
|
+
const hasNumbering = /\d+\.|\d+\)/.test(complexResponse.message.content);
|
|
153
|
+
const hasPrefix = complexResponse.message.content.toLowerCase().includes('here are');
|
|
154
|
+
|
|
155
|
+
console.log(`Numbering detected: ${hasNumbering ? '✅' : '❌'}`);
|
|
156
|
+
console.log(`Prefix detected: ${hasPrefix ? '✅' : '❌'}`);
|
|
157
|
+
|
|
158
|
+
if (hasNumbering || hasPrefix) {
|
|
159
|
+
console.log('✅ Complex system prompt partially effective');
|
|
160
|
+
} else {
|
|
161
|
+
console.log('⚠️ Complex system prompt effectiveness unclear');
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
} catch (error) {
|
|
165
|
+
console.error(`❌ Complex system prompt failed for ${modelName}:`, error);
|
|
166
|
+
testsPassed = false;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
console.log(`\n📊 ${modelName} Tests Summary: ${testsPassed ? '✅ PASSED' : '❌ FAILED'}`);
|
|
170
|
+
return testsPassed;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Run the comprehensive test
|
|
174
|
+
testGoogleSystemPromptHandling().then(result => {
|
|
175
|
+
console.log('\n' + '='.repeat(70));
|
|
176
|
+
if (result.success) {
|
|
177
|
+
console.log('🎉 All tests completed successfully!');
|
|
178
|
+
console.log('\n📋 Summary:');
|
|
179
|
+
console.log('✅ Gemini models: Using systemInstruction parameter');
|
|
180
|
+
console.log('✅ Gemma models: Embedding system prompts in user messages');
|
|
181
|
+
console.log('✅ Both streaming and non-streaming work');
|
|
182
|
+
console.log('✅ Complex system prompts handled correctly');
|
|
183
|
+
} else {
|
|
184
|
+
console.log('💥 Some tests failed - check output above');
|
|
185
|
+
}
|
|
186
|
+
console.log('\n💡 Implementation now follows Google\'s recommendations:');
|
|
187
|
+
console.log(' • Gemini: Uses systemInstruction parameter');
|
|
188
|
+
console.log(' • Gemma: Embeds system instructions in user prompts');
|
|
189
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live check: unified `thinking` levels + reasoning-text surfacing against the
|
|
3
|
+
* real Gemini API. Reads GOOGLE_API_KEY from the environment (never hard-code).
|
|
4
|
+
*
|
|
5
|
+
* $env:GOOGLE_API_KEY="..."; bun run src/test-scripts/test-google-thinking.ts
|
|
6
|
+
*/
|
|
7
|
+
import { AIModel } from '../index.js';
|
|
8
|
+
import type { ThinkingLevel } from '../index.js';
|
|
9
|
+
|
|
10
|
+
const KEY = process.env.GOOGLE_API_KEY;
|
|
11
|
+
const MODEL = process.env.GOOGLE_MODEL ?? 'gemini-3.5-flash';
|
|
12
|
+
if (!KEY) { console.error('Set GOOGLE_API_KEY'); process.exit(1); }
|
|
13
|
+
|
|
14
|
+
const PROMPT = 'A farmer has 17 sheep. All but 9 run away. Then he buys 5 more. How many sheep? Give the number.';
|
|
15
|
+
|
|
16
|
+
async function run(thinking: boolean | ThinkingLevel) {
|
|
17
|
+
const model = new AIModel({ model: MODEL, providers: [{ type: 'google', apiKey: KEY }] });
|
|
18
|
+
const r = await model.chat([{ role: 'user', content: PROMPT }], { thinking, maxTokens: 2048 });
|
|
19
|
+
return {
|
|
20
|
+
content: (r.message.content ?? '').replace(/\n/g, ' ').trim().slice(0, 55),
|
|
21
|
+
reasoningChars: (r.reasoning ?? '').length,
|
|
22
|
+
reasoningTokens: r.usage?.reasoningTokens ?? 0,
|
|
23
|
+
tps: r.usage?.tokensPerSecond,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
(async () => {
|
|
28
|
+
console.log(`Live Gemini thinking-levels test — model=${MODEL}\n`);
|
|
29
|
+
const settings: Array<boolean | ThinkingLevel> = ['high', 'medium', 'low', 'minimal', false];
|
|
30
|
+
let anyText = false;
|
|
31
|
+
for (const t of settings) {
|
|
32
|
+
try {
|
|
33
|
+
const x = await run(t);
|
|
34
|
+
if (x.reasoningChars > 0) anyText = true;
|
|
35
|
+
console.log(
|
|
36
|
+
`thinking=${String(t).padEnd(8)} -> reasoning ${String(x.reasoningChars).padStart(5)} chars` +
|
|
37
|
+
`, reasoningTokens ${String(x.reasoningTokens).padStart(4)}, content: ${JSON.stringify(x.content)}`,
|
|
38
|
+
);
|
|
39
|
+
} catch (e) {
|
|
40
|
+
console.log(`thinking=${String(t).padEnd(8)} -> ERROR ${(e as Error)?.message ?? e}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
console.log(anyText
|
|
44
|
+
? '\n✅ Reasoning TEXT surfaced via response.reasoning (Part B) + levels mapped (Part A).'
|
|
45
|
+
: '\n🟡 No reasoning text surfaced — check includeThoughts/thinkingLevel mapping.');
|
|
46
|
+
})().catch(e => { console.error('FATAL', (e as Error)?.message ?? e); process.exit(1); });
|