recursive-llm-ts 5.0.1 → 5.0.2
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/package.json +6 -3
- package/bin/rlm-go +0 -0
- package/go/README.md +0 -426
- package/go/integration_test.sh +0 -169
- package/go/rlm/benchmark_test.go +0 -168
- package/go/rlm/context_overflow_test.go +0 -1271
- package/go/rlm/context_savings_test.go +0 -387
- package/go/rlm/lcm_episodes_test.go +0 -384
- package/go/rlm/lcm_test.go +0 -1407
- package/go/rlm/meta_agent_test.go +0 -270
- package/go/rlm/observability_test.go +0 -252
- package/go/rlm/parser_test.go +0 -202
- package/go/rlm/repl_test.go +0 -291
- package/go/rlm/schema_test.go +0 -343
- package/go/rlm/store_backend_test.go +0 -428
- package/go/rlm/structured_test.go +0 -895
- package/go/rlm/textrank_test.go +0 -335
- package/go/rlm/tfidf_test.go +0 -272
- package/go/rlm/token_tracking_test.go +0 -859
- package/go/rlm/tokenizer_test.go +0 -305
- package/go/rlm.test +0 -0
- package/go/test_mock.sh +0 -90
- package/go/test_rlm.sh +0 -41
- package/go/test_simple.sh +0 -78
package/package.json
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "recursive-llm-ts",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.2",
|
|
4
4
|
"description": "TypeScript bridge for recursive-llm: Recursive Language Models for unbounded context processing with structured outputs",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"dist",
|
|
9
|
-
"
|
|
10
|
-
"go",
|
|
9
|
+
"go/cmd",
|
|
10
|
+
"go/go.mod",
|
|
11
|
+
"go/go.sum",
|
|
12
|
+
"go/rlm/*.go",
|
|
13
|
+
"!go/rlm/*_test.go",
|
|
11
14
|
"scripts/build-go-binary.js"
|
|
12
15
|
],
|
|
13
16
|
"scripts": {
|
package/bin/rlm-go
DELETED
|
Binary file
|
package/go/README.md
DELETED
|
@@ -1,426 +0,0 @@
|
|
|
1
|
-
# RLM Go Module
|
|
2
|
-
|
|
3
|
-
Go implementation of Recursive Language Models (RLM) based on the [original Python implementation](https://github.com/alexzhang13/rlm).
|
|
4
|
-
|
|
5
|
-
## Overview
|
|
6
|
-
|
|
7
|
-
This is both a standalone Go library and CLI binary that implements the RLM algorithm, allowing language models to process extremely long contexts (100k+ tokens) by storing context as a variable and allowing recursive exploration.
|
|
8
|
-
|
|
9
|
-
**Key Difference from Python**: Uses JavaScript REPL instead of Python REPL for code execution.
|
|
10
|
-
|
|
11
|
-
## Installation
|
|
12
|
-
|
|
13
|
-
### As a Go Library
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
go get github.com/howlerops/recursive-llm-ts/go
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
### Usage as Library
|
|
20
|
-
|
|
21
|
-
```go
|
|
22
|
-
package main
|
|
23
|
-
|
|
24
|
-
import (
|
|
25
|
-
"fmt"
|
|
26
|
-
"os"
|
|
27
|
-
|
|
28
|
-
"github.com/howlerops/recursive-llm-ts/go/rlm"
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
func main() {
|
|
32
|
-
config := rlm.Config{
|
|
33
|
-
MaxDepth: 5,
|
|
34
|
-
MaxIterations: 30,
|
|
35
|
-
APIKey: os.Getenv("OPENAI_API_KEY"),
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
engine := rlm.New("gpt-4o-mini", config)
|
|
39
|
-
|
|
40
|
-
answer, stats, err := engine.Completion(
|
|
41
|
-
"What are the key themes?",
|
|
42
|
-
"Your long document here...",
|
|
43
|
-
)
|
|
44
|
-
if err != nil {
|
|
45
|
-
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
|
|
46
|
-
os.Exit(1)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
fmt.Printf("Answer: %s\n", answer)
|
|
50
|
-
fmt.Printf("Stats: %d LLM calls, %d iterations\n",
|
|
51
|
-
stats.LlmCalls, stats.Iterations)
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### Structured Output
|
|
56
|
-
|
|
57
|
-
```go
|
|
58
|
-
schema := &rlm.JSONSchema{
|
|
59
|
-
Type: "object",
|
|
60
|
-
Properties: map[string]*rlm.JSONSchema{
|
|
61
|
-
"summary": {Type: "string"},
|
|
62
|
-
"score": {Type: "number"},
|
|
63
|
-
},
|
|
64
|
-
Required: []string{"summary", "score"},
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
config := &rlm.StructuredConfig{
|
|
68
|
-
Schema: schema,
|
|
69
|
-
MaxRetries: 3,
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
result, stats, err := engine.StructuredCompletion(
|
|
73
|
-
"Summarize and score",
|
|
74
|
-
document,
|
|
75
|
-
config,
|
|
76
|
-
)
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
## Building the CLI Binary
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
# Build the binary
|
|
83
|
-
go build -o rlm-go ./cmd/rlm
|
|
84
|
-
|
|
85
|
-
# Run tests
|
|
86
|
-
go test ./rlm/... -v
|
|
87
|
-
|
|
88
|
-
# Build with optimization
|
|
89
|
-
go build -ldflags="-s -w" -o rlm-go ./cmd/rlm
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
## Usage
|
|
93
|
-
|
|
94
|
-
The binary accepts JSON input on stdin and returns JSON output on stdout.
|
|
95
|
-
|
|
96
|
-
### Input Format
|
|
97
|
-
|
|
98
|
-
```json
|
|
99
|
-
{
|
|
100
|
-
"model": "gpt-4o-mini",
|
|
101
|
-
"query": "What are the main themes?",
|
|
102
|
-
"context": "Your long document here...",
|
|
103
|
-
"config": {
|
|
104
|
-
"recursive_model": "gpt-4o-mini",
|
|
105
|
-
"api_base": "https://api.openai.com/v1",
|
|
106
|
-
"api_key": "sk-...",
|
|
107
|
-
"max_depth": 5,
|
|
108
|
-
"max_iterations": 30,
|
|
109
|
-
"temperature": 0.7
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
### Output Format
|
|
115
|
-
|
|
116
|
-
```json
|
|
117
|
-
{
|
|
118
|
-
"result": "The main themes are...",
|
|
119
|
-
"stats": {
|
|
120
|
-
"llm_calls": 3,
|
|
121
|
-
"iterations": 2,
|
|
122
|
-
"depth": 0
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### Example
|
|
128
|
-
|
|
129
|
-
```bash
|
|
130
|
-
# Basic usage
|
|
131
|
-
echo '{
|
|
132
|
-
"model": "gpt-4o-mini",
|
|
133
|
-
"query": "Summarize this",
|
|
134
|
-
"context": "Long document...",
|
|
135
|
-
"config": {
|
|
136
|
-
"api_key": "sk-..."
|
|
137
|
-
}
|
|
138
|
-
}' | ./rlm
|
|
139
|
-
|
|
140
|
-
# With environment variable for API key
|
|
141
|
-
export OPENAI_API_KEY="sk-..."
|
|
142
|
-
echo '{
|
|
143
|
-
"model": "gpt-4o-mini",
|
|
144
|
-
"query": "What is this about?",
|
|
145
|
-
"context": "Document text..."
|
|
146
|
-
}' | ./rlm
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Configuration Options
|
|
150
|
-
|
|
151
|
-
All fields in `config` are optional and have defaults:
|
|
152
|
-
|
|
153
|
-
| Field | Type | Default | Description |
|
|
154
|
-
|-------|------|---------|-------------|
|
|
155
|
-
| `recursive_model` | string | Same as `model` | Cheaper model for recursive calls |
|
|
156
|
-
| `api_base` | string | `https://api.openai.com/v1` | API endpoint URL |
|
|
157
|
-
| `api_key` | string | From `OPENAI_API_KEY` env | API key for authentication |
|
|
158
|
-
| `max_depth` | int | 5 | Maximum recursion depth |
|
|
159
|
-
| `max_iterations` | int | 30 | Maximum REPL iterations per call |
|
|
160
|
-
| `temperature` | float | 0.7 | LLM temperature (0-2) |
|
|
161
|
-
| `timeout` | int | 60 | HTTP timeout in seconds |
|
|
162
|
-
| `context_overflow.enabled` | bool | true | Enable context overflow recovery |
|
|
163
|
-
| `context_overflow.strategy` | string | `mapreduce` | Reduction strategy: mapreduce, truncate, chunked, tfidf, textrank, refine |
|
|
164
|
-
| `context_overflow.max_model_tokens` | int | 0 (auto) | Override detected model token limit |
|
|
165
|
-
| `context_overflow.safety_margin` | float | 0.15 | Fraction reserved for prompt overhead |
|
|
166
|
-
| `context_overflow.max_reduction_attempts` | int | 3 | Max retry attempts |
|
|
167
|
-
|
|
168
|
-
Any other fields in `config` are passed as extra parameters to the LLM API.
|
|
169
|
-
|
|
170
|
-
## JavaScript REPL Environment
|
|
171
|
-
|
|
172
|
-
The LLM can write JavaScript code to explore the context. Available globals:
|
|
173
|
-
|
|
174
|
-
### Core Variables
|
|
175
|
-
- `context` - The document to analyze (string)
|
|
176
|
-
- `query` - The user's question (string)
|
|
177
|
-
- `recursive_llm(sub_query, sub_context)` - Recursively process sub-context
|
|
178
|
-
|
|
179
|
-
### String Operations
|
|
180
|
-
```javascript
|
|
181
|
-
context.slice(0, 100) // First 100 chars
|
|
182
|
-
context.split('\n') // Split by newline
|
|
183
|
-
context.length // String length
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
### Regex (Python-style API)
|
|
187
|
-
```javascript
|
|
188
|
-
re.findall("ERROR", context) // Find all matches
|
|
189
|
-
re.search("ERROR", context) // Find first match
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### Built-in Functions
|
|
193
|
-
```javascript
|
|
194
|
-
len(context) // Length of string/array
|
|
195
|
-
print("hello") // Print output
|
|
196
|
-
console.log("hello") // Same as print
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### JSON
|
|
200
|
-
```javascript
|
|
201
|
-
json.loads('{"key":"value"}') // Parse JSON
|
|
202
|
-
json.dumps({key: "value"}) // Stringify JSON
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
### Array Operations
|
|
206
|
-
```javascript
|
|
207
|
-
range(5) // [0, 1, 2, 3, 4]
|
|
208
|
-
range(2, 5) // [2, 3, 4]
|
|
209
|
-
sorted([3, 1, 2]) // [1, 2, 3]
|
|
210
|
-
sum([1, 2, 3]) // 6
|
|
211
|
-
min([1, 2, 3]) // 1
|
|
212
|
-
max([1, 2, 3]) // 3
|
|
213
|
-
enumerate(['a', 'b']) // [[0,'a'], [1,'b']]
|
|
214
|
-
zip([1, 2], ['a', 'b']) // [[1,'a'], [2,'b']]
|
|
215
|
-
any([false, true]) // true
|
|
216
|
-
all([true, true]) // true
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Counting & Grouping
|
|
220
|
-
```javascript
|
|
221
|
-
Counter("hello") // {h:1, e:1, l:2, o:1}
|
|
222
|
-
defaultdict(() => 0) // Dict with default values
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### Math
|
|
226
|
-
```javascript
|
|
227
|
-
Math.floor(3.7) // 3
|
|
228
|
-
Math.ceil(3.2) // 4
|
|
229
|
-
Math.max(1, 2, 3) // 3
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### Returning Results
|
|
233
|
-
```javascript
|
|
234
|
-
// Option 1: Direct answer (write as text, not code)
|
|
235
|
-
FINAL("The answer is 42")
|
|
236
|
-
|
|
237
|
-
// Option 2: Return a variable
|
|
238
|
-
const answer = "The answer is 42"
|
|
239
|
-
FINAL_VAR(answer)
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
## Supported LLM Providers
|
|
243
|
-
|
|
244
|
-
Works with any OpenAI-compatible API:
|
|
245
|
-
|
|
246
|
-
- **OpenAI**: `model: "gpt-4o"`, `model: "gpt-4o-mini"`
|
|
247
|
-
- **Azure OpenAI**: Set custom `api_base`
|
|
248
|
-
- **Ollama**: `api_base: "http://localhost:11434/v1"`, `model: "llama3.2"`
|
|
249
|
-
- **llama.cpp**: `api_base: "http://localhost:8000/v1"`
|
|
250
|
-
- **vLLM**: `api_base: "http://localhost:8000/v1"`
|
|
251
|
-
- Any other OpenAI-compatible endpoint
|
|
252
|
-
|
|
253
|
-
## Architecture
|
|
254
|
-
|
|
255
|
-
```
|
|
256
|
-
cmd/rlm/main.go # CLI entry point (JSON I/O)
|
|
257
|
-
rlm/ # Public package (importable)
|
|
258
|
-
├── doc.go # Package documentation
|
|
259
|
-
├── rlm.go # Core RLM logic
|
|
260
|
-
├── types.go # Config and stats types
|
|
261
|
-
├── structured.go # Structured completion with schema validation
|
|
262
|
-
├── parser.go # FINAL() extraction
|
|
263
|
-
├── prompt.go # System prompt builder
|
|
264
|
-
├── repl.go # JavaScript REPL (goja)
|
|
265
|
-
├── openai.go # OpenAI API client
|
|
266
|
-
├── errors.go # Error types
|
|
267
|
-
├── context_overflow.go # Context overflow detection + 6 reduction strategies
|
|
268
|
-
├── tfidf.go # TF-IDF extractive compression (pure Go)
|
|
269
|
-
└── textrank.go # TextRank graph-based ranking with PageRank
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
## Error Handling
|
|
273
|
-
|
|
274
|
-
Errors are written to stderr with exit code 1:
|
|
275
|
-
|
|
276
|
-
```bash
|
|
277
|
-
# Missing model
|
|
278
|
-
echo '{"query":"test"}' | ./rlm
|
|
279
|
-
# stderr: Missing model in request payload
|
|
280
|
-
|
|
281
|
-
# API error
|
|
282
|
-
echo '{
|
|
283
|
-
"model": "invalid",
|
|
284
|
-
"query": "test",
|
|
285
|
-
"context": "test"
|
|
286
|
-
}' | ./rlm 2>&1
|
|
287
|
-
# stderr: LLM request failed (401): ...
|
|
288
|
-
```
|
|
289
|
-
|
|
290
|
-
## Testing
|
|
291
|
-
|
|
292
|
-
```bash
|
|
293
|
-
# Run all tests
|
|
294
|
-
go test ./rlm/... -v
|
|
295
|
-
|
|
296
|
-
# Run specific test
|
|
297
|
-
go test ./rlm -run TestParser -v
|
|
298
|
-
|
|
299
|
-
# With coverage
|
|
300
|
-
go test ./rlm/... -cover
|
|
301
|
-
|
|
302
|
-
# Benchmark
|
|
303
|
-
go test ./rlm/... -bench=. -benchmem
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
## Performance
|
|
307
|
-
|
|
308
|
-
- **Binary size**: ~15MB (uncompressed), ~5MB (compressed with UPX)
|
|
309
|
-
- **Memory**: ~50MB baseline + context size
|
|
310
|
-
- **Startup**: <10ms
|
|
311
|
-
- **REPL overhead**: ~1-2ms per iteration
|
|
312
|
-
|
|
313
|
-
## Comparison with Python Implementation
|
|
314
|
-
|
|
315
|
-
| Feature | Python | Go |
|
|
316
|
-
|---------|--------|-----|
|
|
317
|
-
| **REPL Language** | Python (RestrictedPython) | JavaScript (goja) |
|
|
318
|
-
| **LLM Providers** | 100+ via LiteLLM | OpenAI-compatible only |
|
|
319
|
-
| **Async Support** | ✅ Full async/await | ❌ Synchronous only |
|
|
320
|
-
| **Distribution** | Requires Python runtime | ✅ Single binary |
|
|
321
|
-
| **Startup Time** | ~500ms | ~10ms |
|
|
322
|
-
| **Memory Usage** | ~150MB | ~50MB |
|
|
323
|
-
|
|
324
|
-
## Known Limitations
|
|
325
|
-
|
|
326
|
-
1. **JavaScript vs Python**: LLMs are more familiar with Python, may need more iterations
|
|
327
|
-
2. **No async**: Recursive calls are sequential, not parallel
|
|
328
|
-
3. **OpenAI API only**: Doesn't support all LiteLLM providers
|
|
329
|
-
4. **No streaming**: Full response only
|
|
330
|
-
|
|
331
|
-
## Integration with TypeScript
|
|
332
|
-
|
|
333
|
-
From Node.js/TypeScript:
|
|
334
|
-
|
|
335
|
-
```typescript
|
|
336
|
-
import { spawn } from 'child_process';
|
|
337
|
-
|
|
338
|
-
interface RLMRequest {
|
|
339
|
-
model: string;
|
|
340
|
-
query: string;
|
|
341
|
-
context: string;
|
|
342
|
-
config?: {
|
|
343
|
-
api_key?: string;
|
|
344
|
-
max_depth?: number;
|
|
345
|
-
max_iterations?: number;
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
interface RLMResponse {
|
|
350
|
-
result: string;
|
|
351
|
-
stats: {
|
|
352
|
-
llm_calls: number;
|
|
353
|
-
iterations: number;
|
|
354
|
-
depth: number;
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
async function callRLM(request: RLMRequest): Promise<RLMResponse> {
|
|
359
|
-
return new Promise((resolve, reject) => {
|
|
360
|
-
const proc = spawn('./rlm');
|
|
361
|
-
let stdout = '';
|
|
362
|
-
let stderr = '';
|
|
363
|
-
|
|
364
|
-
proc.stdout.on('data', (data) => { stdout += data; });
|
|
365
|
-
proc.stderr.on('data', (data) => { stderr += data; });
|
|
366
|
-
|
|
367
|
-
proc.on('close', (code) => {
|
|
368
|
-
if (code !== 0) {
|
|
369
|
-
reject(new Error(stderr || `Exit code ${code}`));
|
|
370
|
-
} else {
|
|
371
|
-
resolve(JSON.parse(stdout));
|
|
372
|
-
}
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
proc.stdin.write(JSON.stringify(request));
|
|
376
|
-
proc.stdin.end();
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// Usage
|
|
381
|
-
const result = await callRLM({
|
|
382
|
-
model: 'gpt-4o-mini',
|
|
383
|
-
query: 'What is this about?',
|
|
384
|
-
context: longDocument,
|
|
385
|
-
config: {
|
|
386
|
-
api_key: process.env.OPENAI_API_KEY,
|
|
387
|
-
},
|
|
388
|
-
});
|
|
389
|
-
|
|
390
|
-
console.log(result.result);
|
|
391
|
-
console.log(`Stats: ${result.stats.llm_calls} LLM calls`);
|
|
392
|
-
```
|
|
393
|
-
|
|
394
|
-
## Troubleshooting
|
|
395
|
-
|
|
396
|
-
### "Missing model in request payload"
|
|
397
|
-
Include the `model` field in your JSON input.
|
|
398
|
-
|
|
399
|
-
### "LLM request failed (401)"
|
|
400
|
-
Check your API key is correct and has sufficient credits.
|
|
401
|
-
|
|
402
|
-
### "max iterations exceeded"
|
|
403
|
-
Increase `max_iterations` in config, or simplify your query.
|
|
404
|
-
|
|
405
|
-
### "max recursion depth exceeded"
|
|
406
|
-
Increase `max_depth` in config.
|
|
407
|
-
|
|
408
|
-
### "Execution error: ReferenceError: xyz is not defined"
|
|
409
|
-
Check the JavaScript syntax. Use `console.log()` not `print()`, or ensure `print()` is available.
|
|
410
|
-
|
|
411
|
-
## Contributing
|
|
412
|
-
|
|
413
|
-
1. Write tests for new features
|
|
414
|
-
2. Ensure all tests pass: `go test ./rlm/... -v`
|
|
415
|
-
3. Format code: `go fmt ./...`
|
|
416
|
-
4. Update documentation
|
|
417
|
-
|
|
418
|
-
## License
|
|
419
|
-
|
|
420
|
-
MIT License - Same as the original Python implementation
|
|
421
|
-
|
|
422
|
-
## Acknowledgments
|
|
423
|
-
|
|
424
|
-
- Based on [Recursive Language Models paper](https://alexzhang13.github.io/blog/2025/rlm/) by Alex Zhang and Omar Khattab (MIT)
|
|
425
|
-
- Original Python implementation: https://github.com/alexzhang13/rlm
|
|
426
|
-
- JavaScript engine: [goja](https://github.com/dop251/goja)
|
package/go/integration_test.sh
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Integration test with real LLM API
|
|
3
|
-
# Set OPENAI_API_KEY environment variable before running
|
|
4
|
-
|
|
5
|
-
set -e
|
|
6
|
-
|
|
7
|
-
echo "🧪 RLM Go Integration Tests"
|
|
8
|
-
echo "================================"
|
|
9
|
-
echo ""
|
|
10
|
-
|
|
11
|
-
# Check if binary exists
|
|
12
|
-
if [ ! -f "./rlm" ]; then
|
|
13
|
-
echo "❌ Binary not found. Building..."
|
|
14
|
-
go build -o rlm ./cmd/rlm
|
|
15
|
-
echo "✅ Built binary"
|
|
16
|
-
fi
|
|
17
|
-
|
|
18
|
-
# Check for API key
|
|
19
|
-
if [ -z "$OPENAI_API_KEY" ]; then
|
|
20
|
-
echo "❌ OPENAI_API_KEY environment variable not set"
|
|
21
|
-
echo ""
|
|
22
|
-
echo "Usage:"
|
|
23
|
-
echo " export OPENAI_API_KEY='sk-...'"
|
|
24
|
-
echo " ./integration_test.sh"
|
|
25
|
-
exit 1
|
|
26
|
-
fi
|
|
27
|
-
|
|
28
|
-
echo "✅ API key found"
|
|
29
|
-
echo ""
|
|
30
|
-
|
|
31
|
-
# Test 1: Simple query
|
|
32
|
-
echo "📝 Test 1: Simple context analysis"
|
|
33
|
-
echo "-----------------------------------"
|
|
34
|
-
RESULT=$(cat <<EOF | ./rlm
|
|
35
|
-
{
|
|
36
|
-
"model": "gpt-4o-mini",
|
|
37
|
-
"query": "How many times does the word 'test' appear?",
|
|
38
|
-
"context": "This is a test. Another test here. Final test.",
|
|
39
|
-
"config": {
|
|
40
|
-
"api_key": "$OPENAI_API_KEY",
|
|
41
|
-
"max_iterations": 10
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
EOF
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
if [ $? -eq 0 ]; then
|
|
48
|
-
echo "✅ Test 1 passed"
|
|
49
|
-
echo "Result: $(echo $RESULT | jq -r '.result')"
|
|
50
|
-
echo "Stats: $(echo $RESULT | jq '.stats')"
|
|
51
|
-
else
|
|
52
|
-
echo "❌ Test 1 failed"
|
|
53
|
-
exit 1
|
|
54
|
-
fi
|
|
55
|
-
echo ""
|
|
56
|
-
|
|
57
|
-
# Test 2: Count/aggregation
|
|
58
|
-
echo "📝 Test 2: Counting errors in logs"
|
|
59
|
-
echo "-----------------------------------"
|
|
60
|
-
LOG_CONTEXT='2024-01-01 INFO: System started
|
|
61
|
-
2024-01-01 ERROR: Connection failed
|
|
62
|
-
2024-01-01 INFO: Retrying
|
|
63
|
-
2024-01-01 ERROR: Timeout
|
|
64
|
-
2024-01-01 ERROR: Failed again
|
|
65
|
-
2024-01-01 INFO: Success'
|
|
66
|
-
|
|
67
|
-
RESULT=$(./rlm <<EOF
|
|
68
|
-
{
|
|
69
|
-
"model": "gpt-4o-mini",
|
|
70
|
-
"query": "Count how many ERROR entries are in the logs",
|
|
71
|
-
"context": "$LOG_CONTEXT",
|
|
72
|
-
"config": {
|
|
73
|
-
"api_key": "$OPENAI_API_KEY",
|
|
74
|
-
"max_iterations": 10
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
EOF
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
if [ $? -eq 0 ]; then
|
|
81
|
-
echo "✅ Test 2 passed"
|
|
82
|
-
echo "Result: $(echo $RESULT | jq -r '.result')"
|
|
83
|
-
ITERATIONS=$(echo $RESULT | jq '.stats.iterations')
|
|
84
|
-
echo "Iterations: $ITERATIONS"
|
|
85
|
-
else
|
|
86
|
-
echo "❌ Test 2 failed"
|
|
87
|
-
exit 1
|
|
88
|
-
fi
|
|
89
|
-
echo ""
|
|
90
|
-
|
|
91
|
-
# Test 3: Long context
|
|
92
|
-
echo "📝 Test 3: Long context processing"
|
|
93
|
-
echo "-----------------------------------"
|
|
94
|
-
LONG_CONTEXT=$(cat <<EOF
|
|
95
|
-
Chapter 1: The Beginning
|
|
96
|
-
|
|
97
|
-
It was a dark and stormy night. The hero embarked on a journey.
|
|
98
|
-
$(for i in {1..100}; do echo "Line $i of the story continues here with more content."; done)
|
|
99
|
-
|
|
100
|
-
Chapter 2: The Middle
|
|
101
|
-
|
|
102
|
-
The hero faced many challenges.
|
|
103
|
-
$(for i in {1..100}; do echo "Line $i describes the adventure."; done)
|
|
104
|
-
|
|
105
|
-
Chapter 3: The End
|
|
106
|
-
|
|
107
|
-
Finally, the hero succeeded and returned home triumphant.
|
|
108
|
-
EOF
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
RESULT=$(cat <<EOF | ./rlm
|
|
112
|
-
{
|
|
113
|
-
"model": "gpt-4o-mini",
|
|
114
|
-
"query": "How many chapters are in this document?",
|
|
115
|
-
"context": "$LONG_CONTEXT",
|
|
116
|
-
"config": {
|
|
117
|
-
"api_key": "$OPENAI_API_KEY",
|
|
118
|
-
"max_iterations": 15
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
EOF
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
if [ $? -eq 0 ]; then
|
|
125
|
-
echo "✅ Test 3 passed"
|
|
126
|
-
echo "Result: $(echo $RESULT | jq -r '.result')"
|
|
127
|
-
LLM_CALLS=$(echo $RESULT | jq '.stats.llm_calls')
|
|
128
|
-
echo "LLM calls: $LLM_CALLS"
|
|
129
|
-
else
|
|
130
|
-
echo "❌ Test 3 failed"
|
|
131
|
-
exit 1
|
|
132
|
-
fi
|
|
133
|
-
echo ""
|
|
134
|
-
|
|
135
|
-
# Test 4: Different model configurations
|
|
136
|
-
echo "📝 Test 4: Two-model configuration"
|
|
137
|
-
echo "-----------------------------------"
|
|
138
|
-
RESULT=$(cat <<EOF | ./rlm
|
|
139
|
-
{
|
|
140
|
-
"model": "gpt-4o",
|
|
141
|
-
"query": "What is this text about?",
|
|
142
|
-
"context": "Artificial intelligence and machine learning are transforming technology.",
|
|
143
|
-
"config": {
|
|
144
|
-
"recursive_model": "gpt-4o-mini",
|
|
145
|
-
"api_key": "$OPENAI_API_KEY",
|
|
146
|
-
"max_iterations": 10,
|
|
147
|
-
"temperature": 0.3
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
EOF
|
|
151
|
-
)
|
|
152
|
-
|
|
153
|
-
if [ $? -eq 0 ]; then
|
|
154
|
-
echo "✅ Test 4 passed"
|
|
155
|
-
echo "Result: $(echo $RESULT | jq -r '.result')"
|
|
156
|
-
else
|
|
157
|
-
echo "❌ Test 4 failed"
|
|
158
|
-
exit 1
|
|
159
|
-
fi
|
|
160
|
-
echo ""
|
|
161
|
-
|
|
162
|
-
echo "================================"
|
|
163
|
-
echo "✅ All integration tests passed!"
|
|
164
|
-
echo ""
|
|
165
|
-
echo "Summary:"
|
|
166
|
-
echo " - Simple queries work"
|
|
167
|
-
echo " - Counting/aggregation works"
|
|
168
|
-
echo " - Long context works"
|
|
169
|
-
echo " - Model configuration works"
|