lazlo-ai 1.0.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/.env.example +9 -0
- package/README.md +278 -0
- package/dist/cache/semantic.d.ts +39 -0
- package/dist/cache/semantic.d.ts.map +1 -0
- package/dist/cache/semantic.js +134 -0
- package/dist/cache/semantic.js.map +1 -0
- package/dist/chains/llmchain.d.ts +65 -0
- package/dist/chains/llmchain.d.ts.map +1 -0
- package/dist/chains/llmchain.js +137 -0
- package/dist/chains/llmchain.js.map +1 -0
- package/dist/chains/rag.d.ts +23 -0
- package/dist/chains/rag.d.ts.map +1 -0
- package/dist/chains/rag.js +47 -0
- package/dist/chains/rag.js.map +1 -0
- package/dist/core/types.d.ts +130 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +8 -0
- package/dist/core/types.js.map +1 -0
- package/dist/document_loaders/index.d.ts +61 -0
- package/dist/document_loaders/index.d.ts.map +1 -0
- package/dist/document_loaders/index.js +183 -0
- package/dist/document_loaders/index.js.map +1 -0
- package/dist/embeddings/google.d.ts +43 -0
- package/dist/embeddings/google.d.ts.map +1 -0
- package/dist/embeddings/google.js +90 -0
- package/dist/embeddings/google.js.map +1 -0
- package/dist/embeddings/local.d.ts +64 -0
- package/dist/embeddings/local.d.ts.map +1 -0
- package/dist/embeddings/local.js +95 -0
- package/dist/embeddings/local.js.map +1 -0
- package/dist/evals/judge.d.ts +22 -0
- package/dist/evals/judge.d.ts.map +1 -0
- package/dist/evals/judge.js +77 -0
- package/dist/evals/judge.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/buffer.d.ts +64 -0
- package/dist/memory/buffer.d.ts.map +1 -0
- package/dist/memory/buffer.js +168 -0
- package/dist/memory/buffer.js.map +1 -0
- package/dist/parsers/output.d.ts +64 -0
- package/dist/parsers/output.d.ts.map +1 -0
- package/dist/parsers/output.js +148 -0
- package/dist/parsers/output.js.map +1 -0
- package/dist/prompts/registry.d.ts +65 -0
- package/dist/prompts/registry.d.ts.map +1 -0
- package/dist/prompts/registry.js +170 -0
- package/dist/prompts/registry.js.map +1 -0
- package/dist/providers/ollama.d.ts +30 -0
- package/dist/providers/ollama.d.ts.map +1 -0
- package/dist/providers/ollama.js +104 -0
- package/dist/providers/ollama.js.map +1 -0
- package/dist/providers/openai.d.ts +46 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +228 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/retrievers/index.d.ts +71 -0
- package/dist/retrievers/index.d.ts.map +1 -0
- package/dist/retrievers/index.js +130 -0
- package/dist/retrievers/index.js.map +1 -0
- package/dist/router/smartrouter.d.ts +36 -0
- package/dist/router/smartrouter.d.ts.map +1 -0
- package/dist/router/smartrouter.js +132 -0
- package/dist/router/smartrouter.js.map +1 -0
- package/dist/text_splitters/index.d.ts +28 -0
- package/dist/text_splitters/index.d.ts.map +1 -0
- package/dist/text_splitters/index.js +109 -0
- package/dist/text_splitters/index.js.map +1 -0
- package/dist/tools/decorator.d.ts +26 -0
- package/dist/tools/decorator.d.ts.map +1 -0
- package/dist/tools/decorator.js +102 -0
- package/dist/tools/decorator.js.map +1 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/keiro.d.ts +20 -0
- package/dist/tools/keiro.d.ts.map +1 -0
- package/dist/tools/keiro.js +67 -0
- package/dist/tools/keiro.js.map +1 -0
- package/dist/tracing/tracer.d.ts +56 -0
- package/dist/tracing/tracer.d.ts.map +1 -0
- package/dist/tracing/tracer.js +125 -0
- package/dist/tracing/tracer.js.map +1 -0
- package/dist/utils/logger.d.ts +25 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +50 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/pricing.d.ts +31 -0
- package/dist/utils/pricing.d.ts.map +1 -0
- package/dist/utils/pricing.js +108 -0
- package/dist/utils/pricing.js.map +1 -0
- package/dist/vectorstores/index.d.ts +62 -0
- package/dist/vectorstores/index.d.ts.map +1 -0
- package/dist/vectorstores/index.js +244 -0
- package/dist/vectorstores/index.js.map +1 -0
- package/package.json +48 -0
- package/src/cache/semantic.ts +175 -0
- package/src/chains/llmchain.ts +194 -0
- package/src/chains/rag.ts +65 -0
- package/src/core/types.ts +178 -0
- package/src/document_loaders/index.ts +223 -0
- package/src/embeddings/google.ts +119 -0
- package/src/embeddings/local.ts +118 -0
- package/src/evals/judge.ts +99 -0
- package/src/index.ts +121 -0
- package/src/memory/buffer.ts +222 -0
- package/src/parsers/output.ts +195 -0
- package/src/prompts/registry.ts +205 -0
- package/src/providers/ollama.ts +151 -0
- package/src/providers/openai.ts +320 -0
- package/src/retrievers/index.ts +182 -0
- package/src/router/smartrouter.ts +172 -0
- package/src/text_splitters/index.ts +145 -0
- package/src/tools/decorator.ts +145 -0
- package/src/tools/index.ts +7 -0
- package/src/tools/keiro.ts +92 -0
- package/src/tracing/tracer.ts +178 -0
- package/src/utils/logger.ts +62 -0
- package/src/utils/pricing.ts +133 -0
- package/src/vectorstores/index.ts +338 -0
- package/test-full.mjs +552 -0
- package/test.mjs +74 -0
- package/tsconfig.json +30 -0
package/test-full.mjs
ADDED
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* COMPREHENSIVE FEATURE TEST - ALL LAZLO JS FEATURES
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
// Providers
|
|
7
|
+
OpenAI,
|
|
8
|
+
Ollama,
|
|
9
|
+
|
|
10
|
+
// Chains
|
|
11
|
+
LLMChain,
|
|
12
|
+
SequentialChain,
|
|
13
|
+
PromptTemplate,
|
|
14
|
+
RetrievalQAChain,
|
|
15
|
+
createRetrievalChain,
|
|
16
|
+
|
|
17
|
+
// Router
|
|
18
|
+
SmartRouter,
|
|
19
|
+
|
|
20
|
+
// Cache
|
|
21
|
+
SemanticCache,
|
|
22
|
+
|
|
23
|
+
// Memory
|
|
24
|
+
BufferMemory,
|
|
25
|
+
TokenBudgetMemory,
|
|
26
|
+
|
|
27
|
+
// Tools
|
|
28
|
+
Tool,
|
|
29
|
+
tool,
|
|
30
|
+
defineTool,
|
|
31
|
+
calculator,
|
|
32
|
+
search,
|
|
33
|
+
weather,
|
|
34
|
+
KeiroSearch,
|
|
35
|
+
|
|
36
|
+
// Tracing
|
|
37
|
+
tracer,
|
|
38
|
+
Tracer,
|
|
39
|
+
|
|
40
|
+
// Evals
|
|
41
|
+
LLMJudge,
|
|
42
|
+
EvalCriteria,
|
|
43
|
+
|
|
44
|
+
// Text Splitters
|
|
45
|
+
CharacterTextSplitter,
|
|
46
|
+
RecursiveCharacterTextSplitter,
|
|
47
|
+
createCharacterSplitter,
|
|
48
|
+
createRecursiveSplitter,
|
|
49
|
+
|
|
50
|
+
// Vector Stores
|
|
51
|
+
InMemoryVectorStore,
|
|
52
|
+
createVectorStore,
|
|
53
|
+
|
|
54
|
+
// Utils
|
|
55
|
+
logger,
|
|
56
|
+
getPricing,
|
|
57
|
+
setPricing,
|
|
58
|
+
calculateCost,
|
|
59
|
+
estimateCost,
|
|
60
|
+
estimateTokens,
|
|
61
|
+
} from './dist/index.js';
|
|
62
|
+
|
|
63
|
+
console.log('\nš§Ŗ LAZLO JS COMPREHENSIVE FEATURE TEST\n');
|
|
64
|
+
console.log('=' .repeat(60));
|
|
65
|
+
|
|
66
|
+
let passed = 0;
|
|
67
|
+
let failed = 0;
|
|
68
|
+
|
|
69
|
+
function test(name, fn) {
|
|
70
|
+
try {
|
|
71
|
+
const result = fn();
|
|
72
|
+
if (result && typeof result.then === 'function') {
|
|
73
|
+
result.then(() => {
|
|
74
|
+
console.log(`ā
${name}`);
|
|
75
|
+
passed++;
|
|
76
|
+
}).catch(e => {
|
|
77
|
+
console.log(`ā ${name}: ${e.message}`);
|
|
78
|
+
failed++;
|
|
79
|
+
});
|
|
80
|
+
} else {
|
|
81
|
+
console.log(`ā
${name}`);
|
|
82
|
+
passed++;
|
|
83
|
+
}
|
|
84
|
+
} catch (e) {
|
|
85
|
+
console.log(`ā ${name}: ${e.message}`);
|
|
86
|
+
failed++;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ============================================================================
|
|
91
|
+
// 1. CORE TYPES
|
|
92
|
+
// ============================================================================
|
|
93
|
+
|
|
94
|
+
console.log('\nš¦ 1. CORE TYPES');
|
|
95
|
+
console.log('-'.repeat(60));
|
|
96
|
+
|
|
97
|
+
test('Message type works (runtime check)', () => {
|
|
98
|
+
const msg = { role: 'user', content: 'test' };
|
|
99
|
+
return msg.role === 'user' && msg.content === 'test';
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('ChatResponse type works (runtime check)', () => {
|
|
103
|
+
const resp = { content: 'hello' };
|
|
104
|
+
return resp.content === 'hello';
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// ============================================================================
|
|
108
|
+
// 2. PROVIDERS
|
|
109
|
+
// ============================================================================
|
|
110
|
+
|
|
111
|
+
console.log('\nš 2. PROVIDERS');
|
|
112
|
+
console.log('-'.repeat(60));
|
|
113
|
+
|
|
114
|
+
test('OpenAI provider instantiates', () => {
|
|
115
|
+
const openai = new OpenAI('test-key', 'gpt-4o');
|
|
116
|
+
return openai.defaultModel === 'gpt-4o';
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('OpenAI supports tools', () => {
|
|
120
|
+
const openai = new OpenAI('test-key');
|
|
121
|
+
return openai.supportsTools === true;
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('OpenAI supports structured output', () => {
|
|
125
|
+
const openai = new OpenAI('test-key');
|
|
126
|
+
return openai.supportsStructuredOutput === true;
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test('Ollama provider instantiates', () => {
|
|
130
|
+
const ollama = new Ollama({ model: 'llama3.2' });
|
|
131
|
+
return ollama.model === 'llama3.2';
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test('Ollama supports tools', () => {
|
|
135
|
+
const ollama = new Ollama();
|
|
136
|
+
return ollama.supportsTools === true;
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// 3. PROMPT TEMPLATE
|
|
141
|
+
// ============================================================================
|
|
142
|
+
|
|
143
|
+
console.log('\nš 3. PROMPT TEMPLATE');
|
|
144
|
+
console.log('-'.repeat(60));
|
|
145
|
+
|
|
146
|
+
test('PromptTemplate basic format', () => {
|
|
147
|
+
const p = new PromptTemplate('Hello {name}!');
|
|
148
|
+
return p.format({ name: 'World' }) === 'Hello World!';
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test('PromptTemplate inputVars extracted', () => {
|
|
152
|
+
const p = new PromptTemplate('Hello {name}, you are {role}');
|
|
153
|
+
return p.inputVars.length === 2;
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// ============================================================================
|
|
157
|
+
// 4. LLM CHAIN
|
|
158
|
+
// ============================================================================
|
|
159
|
+
|
|
160
|
+
console.log('\nāļø 4. LLM CHAIN');
|
|
161
|
+
console.log('-'.repeat(60));
|
|
162
|
+
|
|
163
|
+
test('LLMChain instantiates with mock LLM', () => {
|
|
164
|
+
const mockLlm = {
|
|
165
|
+
supportsTools: false,
|
|
166
|
+
supportsStructuredOutput: false,
|
|
167
|
+
async invoke() { return { content: 'response', usage: {} }; },
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const chain = new LLMChain({
|
|
171
|
+
llm: mockLlm,
|
|
172
|
+
prompt: new PromptTemplate('Hello {name}'),
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
return chain !== undefined;
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test('LLMChain estimateCost works', () => {
|
|
179
|
+
const mockLlm = {
|
|
180
|
+
defaultModel: 'gpt-4o',
|
|
181
|
+
supportsTools: false,
|
|
182
|
+
supportsStructuredOutput: false,
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const chain = new LLMChain({
|
|
186
|
+
llm: mockLlm,
|
|
187
|
+
prompt: new PromptTemplate('Hello {name}'),
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const estimate = chain.estimateCost({ name: 'World' });
|
|
191
|
+
return estimate.model === 'gpt-4o' && estimate.estimatedCostUsd >= 0;
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// ============================================================================
|
|
195
|
+
// 5. SEQUENTIAL CHAIN
|
|
196
|
+
// ============================================================================
|
|
197
|
+
|
|
198
|
+
console.log('\nš 5. SEQUENTIAL CHAIN');
|
|
199
|
+
console.log('-'.repeat(60));
|
|
200
|
+
|
|
201
|
+
test('SequentialChain instantiates', () => {
|
|
202
|
+
const mockLlm = {
|
|
203
|
+
supportsTools: false,
|
|
204
|
+
supportsStructuredOutput: false,
|
|
205
|
+
async invoke() { return { content: 'response' }; },
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const chain1 = new LLMChain({
|
|
209
|
+
llm: mockLlm,
|
|
210
|
+
prompt: new PromptTemplate('Step 1: {input}'),
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const chain2 = new LLMChain({
|
|
214
|
+
llm: mockLlm,
|
|
215
|
+
prompt: new PromptTemplate('Step 2: {output}'),
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
const seqChain = new SequentialChain({
|
|
219
|
+
chains: [chain1, chain2],
|
|
220
|
+
inputVariables: ['input'],
|
|
221
|
+
outputVariables: ['text'],
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
return seqChain !== undefined;
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
// ============================================================================
|
|
228
|
+
// 6. RAG CHAIN
|
|
229
|
+
// ============================================================================
|
|
230
|
+
|
|
231
|
+
console.log('\nš 6. RAG CHAIN');
|
|
232
|
+
console.log('-'.repeat(60));
|
|
233
|
+
|
|
234
|
+
test('RetrievalQAChain factory works', () => {
|
|
235
|
+
const mockLlm = {
|
|
236
|
+
supportsTools: false,
|
|
237
|
+
supportsStructuredOutput: false,
|
|
238
|
+
async invoke() { return { content: 'answer' }; },
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const mockRetriever = {
|
|
242
|
+
async getRelevantDocuments() {
|
|
243
|
+
return [{ pageContent: 'doc1', metadata: {} }];
|
|
244
|
+
},
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const rag = createRetrievalChain(mockLlm, mockRetriever);
|
|
248
|
+
return rag !== undefined;
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// ============================================================================
|
|
252
|
+
// 7. SMART ROUTER
|
|
253
|
+
// ============================================================================
|
|
254
|
+
|
|
255
|
+
console.log('\nš§ 7. SMART ROUTER');
|
|
256
|
+
console.log('-'.repeat(60));
|
|
257
|
+
|
|
258
|
+
test('SmartRouter instantiates', () => {
|
|
259
|
+
const fast = {
|
|
260
|
+
supportsTools: false,
|
|
261
|
+
supportsStructuredOutput: false,
|
|
262
|
+
async invoke() { return { content: 'fast response' }; },
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const smart = {
|
|
266
|
+
supportsTools: false,
|
|
267
|
+
supportsStructuredOutput: false,
|
|
268
|
+
async invoke() { return { content: 'smart response' }; },
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
const router = new SmartRouter({ fast, smart, threshold: 0.5 });
|
|
272
|
+
return router !== undefined;
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
test('SmartRouter printStats works', () => {
|
|
276
|
+
const fast = {
|
|
277
|
+
supportsTools: false,
|
|
278
|
+
supportsStructuredOutput: false,
|
|
279
|
+
async invoke() { return { content: 'fast' }; },
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
const smart = {
|
|
283
|
+
supportsTools: false,
|
|
284
|
+
supportsStructuredOutput: false,
|
|
285
|
+
async invoke() { return { content: 'smart' }; },
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const router = new SmartRouter({ fast, smart });
|
|
289
|
+
router.printStats();
|
|
290
|
+
return true;
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// ============================================================================
|
|
294
|
+
// 8. SEMANTIC CACHE
|
|
295
|
+
// ============================================================================
|
|
296
|
+
|
|
297
|
+
console.log('\nš¾ 8. SEMANTIC CACHE');
|
|
298
|
+
console.log('-'.repeat(60));
|
|
299
|
+
|
|
300
|
+
test('SemanticCache instantiates', () => {
|
|
301
|
+
const cache = new SemanticCache({ threshold: 0.9 });
|
|
302
|
+
return cache !== undefined;
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
test('SemanticCache stores and looks up', () => {
|
|
306
|
+
const cache = new SemanticCache({ threshold: 0.5 });
|
|
307
|
+
cache.put('What is AI?', 'AI is artificial intelligence.');
|
|
308
|
+
const result = cache.lookup('What is AI?');
|
|
309
|
+
return result === 'AI is artificial intelligence.';
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
test('SemanticCache printStats works', () => {
|
|
313
|
+
const cache = new SemanticCache();
|
|
314
|
+
cache.put('test', 'result');
|
|
315
|
+
cache.lookup('test');
|
|
316
|
+
cache.printStats();
|
|
317
|
+
return true;
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
// ============================================================================
|
|
321
|
+
// 9. MEMORY
|
|
322
|
+
// ============================================================================
|
|
323
|
+
|
|
324
|
+
console.log('\nš§ 9. MEMORY');
|
|
325
|
+
console.log('-'.repeat(60));
|
|
326
|
+
|
|
327
|
+
test('BufferMemory save and load', async () => {
|
|
328
|
+
const memory = new BufferMemory();
|
|
329
|
+
await memory.saveContext({ input: 'Hello' }, { text: 'Hi there!' });
|
|
330
|
+
const vars = await memory.loadMemoryVariables({});
|
|
331
|
+
return vars.history !== undefined;
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
test('BufferMemory with max tokens', () => {
|
|
335
|
+
const memory = new BufferMemory({ maxTokenLimit: 100 });
|
|
336
|
+
return memory !== undefined;
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
test('TokenBudgetMemory instantiates', () => {
|
|
340
|
+
const memory = new TokenBudgetMemory({ maxTokens: 4000 });
|
|
341
|
+
return memory !== undefined;
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
test('TokenBudgetMemory tokenUsage', async () => {
|
|
345
|
+
const memory = new TokenBudgetMemory({ maxTokens: 4000 });
|
|
346
|
+
await memory.saveContext({ input: 'Hello' }, { text: 'Hi!' });
|
|
347
|
+
const usage = memory.tokenUsage;
|
|
348
|
+
return usage.budget === 4000;
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
// ============================================================================
|
|
352
|
+
// 10. TOOLS
|
|
353
|
+
// ============================================================================
|
|
354
|
+
|
|
355
|
+
console.log('\nš§ 10. TOOLS');
|
|
356
|
+
console.log('-'.repeat(60));
|
|
357
|
+
|
|
358
|
+
test('Tool class works', async () => {
|
|
359
|
+
const t = new Tool(
|
|
360
|
+
(args) => args.x + args.y,
|
|
361
|
+
{ name: 'add', description: 'Add numbers' }
|
|
362
|
+
);
|
|
363
|
+
const result = await t.invoke({ x: 5, y: 3 });
|
|
364
|
+
return result === '8';
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
test('defineTool factory works', async () => {
|
|
368
|
+
const multiply = defineTool(
|
|
369
|
+
(args) => args.a * args.b,
|
|
370
|
+
'multiply',
|
|
371
|
+
'Multiply two numbers'
|
|
372
|
+
);
|
|
373
|
+
const result = await multiply.invoke({ a: 4, b: 5 });
|
|
374
|
+
return result === '20';
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
test('calculator tool works', async () => {
|
|
378
|
+
const result = await calculator.invoke({ expression: '2 + 2' });
|
|
379
|
+
return result === '4';
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
test('search tool exists', () => {
|
|
383
|
+
return search.name === 'search';
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
test('weather tool exists', () => {
|
|
387
|
+
return weather.name === 'weather';
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
test('KeiroSearch instantiates', () => {
|
|
391
|
+
const keiro = new KeiroSearch();
|
|
392
|
+
return keiro.name === 'keiro_search';
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
// ============================================================================
|
|
396
|
+
// 11. TRACING
|
|
397
|
+
// ============================================================================
|
|
398
|
+
|
|
399
|
+
console.log('\nš 11. TRACING');
|
|
400
|
+
console.log('-'.repeat(60));
|
|
401
|
+
|
|
402
|
+
test('Tracer trace context works', () => {
|
|
403
|
+
const { tracer: t, span, end } = tracer.trace('test');
|
|
404
|
+
span('step1').finish();
|
|
405
|
+
end();
|
|
406
|
+
return true;
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
test('Tracer event works', () => {
|
|
410
|
+
tracer.event('test_event', 'llm', 100, 50);
|
|
411
|
+
return true;
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
test('Tracer printSummary works', () => {
|
|
415
|
+
tracer.printSummary();
|
|
416
|
+
return true;
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
test('Tracer clear works', () => {
|
|
420
|
+
tracer.clear();
|
|
421
|
+
return true;
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
// ============================================================================
|
|
425
|
+
// 12. EVALS
|
|
426
|
+
// ============================================================================
|
|
427
|
+
|
|
428
|
+
console.log('\nāļø 12. EVALS');
|
|
429
|
+
console.log('-'.repeat(60));
|
|
430
|
+
|
|
431
|
+
test('EvalCriteria enum exists', () => {
|
|
432
|
+
return EvalCriteria.ACCURACY === 'accuracy';
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
test('LLMJudge instantiates', () => {
|
|
436
|
+
const mockLlm = {
|
|
437
|
+
supportsTools: false,
|
|
438
|
+
supportsStructuredOutput: false,
|
|
439
|
+
async invoke() {
|
|
440
|
+
return { content: '{"score": 8, "explanation": "good", "passed": true}' };
|
|
441
|
+
},
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
const judge = new LLMJudge(mockLlm);
|
|
445
|
+
return judge !== undefined;
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
// ============================================================================
|
|
449
|
+
// 13. TEXT SPLITTERS
|
|
450
|
+
// ============================================================================
|
|
451
|
+
|
|
452
|
+
console.log('\nāļø 13. TEXT SPLITTERS');
|
|
453
|
+
console.log('-'.repeat(60));
|
|
454
|
+
|
|
455
|
+
test('CharacterTextSplitter works', () => {
|
|
456
|
+
const splitter = new CharacterTextSplitter({ chunkSize: 10 });
|
|
457
|
+
const chunks = splitter.splitText('Hello World Test');
|
|
458
|
+
return chunks.length > 1;
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
test('RecursiveCharacterTextSplitter works', () => {
|
|
462
|
+
const splitter = new RecursiveCharacterTextSplitter({ chunkSize: 20 });
|
|
463
|
+
const chunks = splitter.splitText('This is a long text that needs to be split.');
|
|
464
|
+
return chunks.length >= 1;
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
test('createCharacterSplitter factory', () => {
|
|
468
|
+
const splitter = createCharacterSplitter({ chunkSize: 5 });
|
|
469
|
+
return splitter !== undefined;
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
test('createRecursiveSplitter factory', () => {
|
|
473
|
+
const splitter = createRecursiveSplitter({ chunkSize: 10 });
|
|
474
|
+
return splitter !== undefined;
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
// ============================================================================
|
|
478
|
+
// 14. VECTOR STORES
|
|
479
|
+
// ============================================================================
|
|
480
|
+
|
|
481
|
+
console.log('\nšļø 14. VECTOR STORES');
|
|
482
|
+
console.log('-'.repeat(60));
|
|
483
|
+
|
|
484
|
+
test('InMemoryVectorStore instantiates', () => {
|
|
485
|
+
const mockEmbeddings = {
|
|
486
|
+
async embedQuery() { return new Array(384).fill(0); },
|
|
487
|
+
async embedDocuments() { return [new Array(384).fill(0)]; },
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
const store = new InMemoryVectorStore(mockEmbeddings);
|
|
491
|
+
return store !== undefined;
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
test('createVectorStore factory', () => {
|
|
495
|
+
const store = createVectorStore();
|
|
496
|
+
return store !== undefined;
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
// ============================================================================
|
|
500
|
+
// 15. UTILS
|
|
501
|
+
// ============================================================================
|
|
502
|
+
|
|
503
|
+
console.log('\nš§ 15. UTILS');
|
|
504
|
+
console.log('-'.repeat(60));
|
|
505
|
+
|
|
506
|
+
test('getPricing works', () => {
|
|
507
|
+
const pricing = getPricing('gpt-4o');
|
|
508
|
+
return pricing.input === 2.5 && pricing.output === 10;
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
test('setPricing works', () => {
|
|
512
|
+
setPricing('test-model', 1.0, 2.0);
|
|
513
|
+
const pricing = getPricing('test-model');
|
|
514
|
+
return pricing.input === 1.0;
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
test('calculateCost works', () => {
|
|
518
|
+
const cost = calculateCost('gpt-4o', 1000, 500);
|
|
519
|
+
return cost > 0;
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
test('estimateCost works', () => {
|
|
523
|
+
const cost = estimateCost('gpt-4o', 'Hello world', 'Hi there');
|
|
524
|
+
return cost >= 0;
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
test('estimateTokens works', () => {
|
|
528
|
+
const tokens = estimateTokens('Hello world');
|
|
529
|
+
return tokens > 0;
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
test('logger works', () => {
|
|
533
|
+
logger.info('Test log');
|
|
534
|
+
logger.debug('Debug log');
|
|
535
|
+
logger.warn('Warning log');
|
|
536
|
+
logger.error('Error log');
|
|
537
|
+
return true;
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
// ============================================================================
|
|
541
|
+
// SUMMARY
|
|
542
|
+
// ============================================================================
|
|
543
|
+
|
|
544
|
+
console.log('\n' + '='.repeat(60));
|
|
545
|
+
console.log(`š TEST SUMMARY: ${passed} passed, ${failed} failed`);
|
|
546
|
+
console.log('='.repeat(60));
|
|
547
|
+
|
|
548
|
+
if (failed === 0) {
|
|
549
|
+
console.log('\nš ALL FEATURES VERIFIED AND WORKING!\n');
|
|
550
|
+
} else {
|
|
551
|
+
console.log(`\nā ļø ${failed} tests failed\n`);
|
|
552
|
+
}
|
package/test.mjs
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test script for lazlo-js
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
OpenAI,
|
|
7
|
+
LLMChain,
|
|
8
|
+
PromptTemplate,
|
|
9
|
+
SmartRouter,
|
|
10
|
+
SemanticCache,
|
|
11
|
+
BufferMemory,
|
|
12
|
+
TokenBudgetMemory,
|
|
13
|
+
Tool,
|
|
14
|
+
KeiroSearch,
|
|
15
|
+
tracer,
|
|
16
|
+
LLMJudge,
|
|
17
|
+
EvalCriteria,
|
|
18
|
+
CharacterTextSplitter,
|
|
19
|
+
RecursiveCharacterTextSplitter,
|
|
20
|
+
InMemoryVectorStore,
|
|
21
|
+
logger,
|
|
22
|
+
getPricing,
|
|
23
|
+
setPricing,
|
|
24
|
+
} from './dist/index.js';
|
|
25
|
+
|
|
26
|
+
console.log('ā
All imports successful!\n');
|
|
27
|
+
|
|
28
|
+
// Test 1: Pricing
|
|
29
|
+
console.log('=== Test 1: Pricing ===');
|
|
30
|
+
const gpt4oPricing = getPricing('gpt-4o');
|
|
31
|
+
console.log('gpt-4o pricing:', gpt4oPricing);
|
|
32
|
+
setPricing('test-model', 1.0, 2.0);
|
|
33
|
+
console.log('Custom pricing set:', getPricing('test-model'));
|
|
34
|
+
|
|
35
|
+
// Test 2: PromptTemplate
|
|
36
|
+
console.log('\n=== Test 2: PromptTemplate ===');
|
|
37
|
+
const prompt = new PromptTemplate('Hello {name}, you are {role}');
|
|
38
|
+
const formatted = prompt.format({ name: 'World', role: 'AI' });
|
|
39
|
+
console.log('Formatted prompt:', formatted);
|
|
40
|
+
|
|
41
|
+
// Test 3: BufferMemory
|
|
42
|
+
console.log('\n=== Test 3: BufferMemory ===');
|
|
43
|
+
const memory = new BufferMemory();
|
|
44
|
+
await memory.saveContext({ input: 'Hi' }, { text: 'Hello!' });
|
|
45
|
+
const vars = await memory.loadMemoryVariables({});
|
|
46
|
+
console.log('Memory variables:', vars);
|
|
47
|
+
|
|
48
|
+
// Test 4: Text Splitter
|
|
49
|
+
console.log('\n=== Test 4: TextSplitter ===');
|
|
50
|
+
const splitter = new RecursiveCharacterTextSplitter({ chunkSize: 50 });
|
|
51
|
+
const chunks = splitter.splitText('This is a long text that needs to be split into smaller chunks for processing.');
|
|
52
|
+
console.log('Chunks:', chunks);
|
|
53
|
+
|
|
54
|
+
// Test 5: Tracer
|
|
55
|
+
console.log('\n=== Test 5: Tracer ===');
|
|
56
|
+
const { tracer: t, span, end } = tracer.trace('test_run');
|
|
57
|
+
span('test_span').finish();
|
|
58
|
+
end();
|
|
59
|
+
tracer.printSummary();
|
|
60
|
+
|
|
61
|
+
// Test 6: Logger
|
|
62
|
+
console.log('\n=== Test 6: Logger ===');
|
|
63
|
+
logger.info('Test log message');
|
|
64
|
+
|
|
65
|
+
// Test 7: Tool
|
|
66
|
+
console.log('\n=== Test 7: Tool ===');
|
|
67
|
+
const addTool = new Tool(
|
|
68
|
+
(args) => String(args.a + args.b),
|
|
69
|
+
{ name: 'add', description: 'Add two numbers' }
|
|
70
|
+
);
|
|
71
|
+
const result = await addTool.invoke({ a: 5, b: 3 });
|
|
72
|
+
console.log('Tool result:', result);
|
|
73
|
+
|
|
74
|
+
console.log('\nā
All tests passed!');
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"lib": ["ES2022", "DOM"],
|
|
6
|
+
"moduleResolution": "node",
|
|
7
|
+
"outDir": "./dist",
|
|
8
|
+
"rootDir": "./src",
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"declarationMap": true,
|
|
11
|
+
"sourceMap": true,
|
|
12
|
+
"strict": true,
|
|
13
|
+
"esModuleInterop": true,
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
"forceConsistentCasingInFileNames": true,
|
|
16
|
+
"resolveJsonModule": true,
|
|
17
|
+
"allowSyntheticDefaultImports": true,
|
|
18
|
+
"noImplicitAny": true,
|
|
19
|
+
"strictNullChecks": true,
|
|
20
|
+
"strictFunctionTypes": true,
|
|
21
|
+
"noUnusedLocals": false,
|
|
22
|
+
"noUnusedParameters": false,
|
|
23
|
+
"noImplicitReturns": true,
|
|
24
|
+
"noFallthroughCasesInSwitch": true,
|
|
25
|
+
"allowImportingTsExtensions": false,
|
|
26
|
+
"isolatedModules": true
|
|
27
|
+
},
|
|
28
|
+
"include": ["src/**/*"],
|
|
29
|
+
"exclude": ["node_modules", "dist"]
|
|
30
|
+
}
|