@cloudwarriors-ai/rlm 0.1.7 → 0.1.9
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/dist/application/handlers/llm-query-handler.d.ts +67 -0
- package/dist/application/handlers/llm-query-handler.d.ts.map +1 -0
- package/dist/application/handlers/llm-query-handler.js +169 -0
- package/dist/application/handlers/llm-query-handler.js.map +1 -0
- package/dist/application/query-handler.d.ts +23 -2
- package/dist/application/query-handler.d.ts.map +1 -1
- package/dist/application/query-handler.js +215 -112
- package/dist/application/query-handler.js.map +1 -1
- package/dist/cli/index.js +0 -0
- package/dist/domain/constants.d.ts +124 -0
- package/dist/domain/constants.d.ts.map +1 -0
- package/dist/domain/constants.js +148 -0
- package/dist/domain/constants.js.map +1 -0
- package/dist/domain/errors/index.d.ts +1 -0
- package/dist/domain/errors/index.d.ts.map +1 -1
- package/dist/domain/errors/index.js +2 -0
- package/dist/domain/errors/index.js.map +1 -1
- package/dist/domain/errors/token-budget-error.d.ts +47 -0
- package/dist/domain/errors/token-budget-error.d.ts.map +1 -0
- package/dist/domain/errors/token-budget-error.js +41 -0
- package/dist/domain/errors/token-budget-error.js.map +1 -0
- package/dist/domain/interfaces/code-executor.d.ts +32 -2
- package/dist/domain/interfaces/code-executor.d.ts.map +1 -1
- package/dist/domain/interfaces/event-emitter.d.ts +55 -1
- package/dist/domain/interfaces/event-emitter.d.ts.map +1 -1
- package/dist/domain/interfaces/llm-provider.d.ts +4 -0
- package/dist/domain/interfaces/llm-provider.d.ts.map +1 -1
- package/dist/domain/services/cost-calculator.d.ts.map +1 -1
- package/dist/domain/services/cost-calculator.js +9 -4
- package/dist/domain/services/cost-calculator.js.map +1 -1
- package/dist/domain/types/config.d.ts +17 -0
- package/dist/domain/types/config.d.ts.map +1 -1
- package/dist/domain/types/config.js +41 -0
- package/dist/domain/types/config.js.map +1 -1
- package/dist/domain/types/index-schema.d.ts +206 -0
- package/dist/domain/types/index-schema.d.ts.map +1 -0
- package/dist/domain/types/index-schema.js +41 -0
- package/dist/domain/types/index-schema.js.map +1 -0
- package/dist/domain/types/index.d.ts +2 -0
- package/dist/domain/types/index.d.ts.map +1 -1
- package/dist/domain/types/index.js +4 -0
- package/dist/domain/types/index.js.map +1 -1
- package/dist/domain/utils/timer.d.ts +34 -0
- package/dist/domain/utils/timer.d.ts.map +1 -0
- package/dist/domain/utils/timer.js +39 -0
- package/dist/domain/utils/timer.js.map +1 -0
- package/dist/factory/create-rlm.d.ts.map +1 -1
- package/dist/factory/create-rlm.js +1 -0
- package/dist/factory/create-rlm.js.map +1 -1
- package/dist/infrastructure/llm/openrouter-provider.d.ts +1 -0
- package/dist/infrastructure/llm/openrouter-provider.d.ts.map +1 -1
- package/dist/infrastructure/llm/openrouter-provider.js +30 -9
- package/dist/infrastructure/llm/openrouter-provider.js.map +1 -1
- package/dist/infrastructure/llm/prompts/index.d.ts +1 -1
- package/dist/infrastructure/llm/prompts/index.d.ts.map +1 -1
- package/dist/infrastructure/llm/prompts/index.js +1 -1
- package/dist/infrastructure/llm/prompts/index.js.map +1 -1
- package/dist/infrastructure/llm/prompts/system-prompt.d.ts +14 -1
- package/dist/infrastructure/llm/prompts/system-prompt.d.ts.map +1 -1
- package/dist/infrastructure/llm/prompts/system-prompt.js +186 -52
- package/dist/infrastructure/llm/prompts/system-prompt.js.map +1 -1
- package/dist/infrastructure/logging/debug-logger.d.ts +29 -0
- package/dist/infrastructure/logging/debug-logger.d.ts.map +1 -0
- package/dist/infrastructure/logging/debug-logger.js +35 -0
- package/dist/infrastructure/logging/debug-logger.js.map +1 -0
- package/dist/infrastructure/sandbox/prelude/rlm_prelude.py +637 -41
- package/dist/infrastructure/sandbox/process-manager.d.ts +1 -0
- package/dist/infrastructure/sandbox/process-manager.d.ts.map +1 -1
- package/dist/infrastructure/sandbox/process-manager.js +19 -6
- package/dist/infrastructure/sandbox/process-manager.js.map +1 -1
- package/dist/infrastructure/sandbox/python-executor.d.ts +6 -2
- package/dist/infrastructure/sandbox/python-executor.d.ts.map +1 -1
- package/dist/infrastructure/sandbox/python-executor.js +138 -5
- package/dist/infrastructure/sandbox/python-executor.js.map +1 -1
- package/package.json +2 -1
- package/src/infrastructure/sandbox/prelude/rlm_prelude.py +637 -41
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Base system prompt for RLM
|
|
3
3
|
*/
|
|
4
|
-
export declare const RLM_SYSTEM_PROMPT = "You are an RLM (Recursive Language Model) agent. Your task is to process large contexts by writing Python code that decomposes and recursively processes content.\n\n##
|
|
4
|
+
export declare const RLM_SYSTEM_PROMPT = "You are an RLM (Recursive Language Model) agent. Your task is to process large contexts by writing Python code that decomposes and recursively processes content.\n\n## Token Budget (CRITICAL)\n\nYour token budget per llm_query() call is approximately **125,000 tokens** (~500,000 characters).\nNEVER pass more than 500,000 characters to llm_query() - it will fail with a capacity error.\n\nUse these functions to stay within limits:\n- `count_tokens(text)` - Check token count before calling llm_query()\n- `get_units_safe(ids, max_tokens)` - Automatically fetch units within budget\n\n## CRITICAL: Examine Context First (Before Decomposing)\n\nBefore deciding how to process the context, you MUST examine it:\n\n1. **Check size and structure**:\n ```python\n print(f\"Context: {len(context)} chars, ~{len(context)//4} tokens\")\n print(context[:2000]) # See the beginning\n ```\n\n2. **Scan for patterns** relevant to the query:\n ```python\n import re\n # Find sections that might contain the answer\n matches = re.findall(r'relevant_pattern', context)\n print(f\"Found {len(matches)} potentially relevant sections\")\n ```\n\n3. **THEN decide** how to decompose:\n - Small context? Process directly\n - Found specific matches? Focus on those\n - Large, unfocused? Chunk strategically\n\nDo NOT blindly iterate through all content. Use your judgment to filter and prioritize.\n\n## Available Python Functions\n\n**ONLY USE THESE EXACT FUNCTION NAMES** - any other function will cause \"name not defined\" error.\n\n### Core Functions\n- `llm_query(query: str, *context_vars) -> str` - Make recursive LLM call (max 500K chars)\n- `llm_query_batch(queries: list[tuple[str, str]]) -> list[str]` - **PARALLEL** LLM calls (MUCH faster!)\n- `set_result(result: str) -> None` - Set final answer\n- `set_result_final(result: str, confidence: float = 1.0) -> None` - Set final answer with early termination\n- `set_variable(name: str, value: str) -> None` - Store a variable\n\n### Structure Functions (for codebase with \"=== FILE:\" markers)\n- `get_structure() -> dict` - Returns {type, total_files, units: [{id, path, tokens}]}\n- `get_unit(unit_id: str) -> str` - Get specific unit content\n- `list_units(pattern: str = None) -> list[dict]` - List units matching pattern\n- `get_units_safe(unit_ids: list, max_tokens: int = 50000) -> tuple[str, list]` - Fetch units within budget\n\n### Utility Functions\n- `count_tokens(text: str) -> int` - Estimate tokens (~4 chars/token)\n- `chunk_text(text: str, chunk_size: int = 10000, overlap: int = 500) -> list[str]` - Split text\n- `filter_lines(text: str, predicate: str) -> str` - Filter lines containing predicate\n\n**WRONG NAMES (will error):** get_repo_structure, get_file_list, list_files, get_units, get_repo_info\n\n## Available Context Variables\n\n**CRITICAL: Your code runs in a FRESH, ISOLATED Python environment.**\nThe ONLY variables available to you are:\n\n{context_variables}\n\n**DO NOT** reference any other variables - they will cause \"name not defined\" errors.\n\n## When to Use Which Approach\n\n**If context is SMALL (< 100K tokens / 400K chars):**\n- Just examine the content directly with `print(context[:5000])`\n- Answer the question with `set_result(\"your answer\")`\n- NO need for structure extraction or llm_query()\n\n**If context is LARGE and has structure (contains \"=== FILE:\" markers):**\n- Use `get_structure()` to understand the structure\n- Use `get_units_safe()` to fetch portions\n- Use `llm_query()` to analyze each portion\n\n**If context is LARGE but unstructured:**\n- Use `chunk_text()` to split into pieces\n- Use `llm_query()` on each chunk\n\n## Guidelines\n\n1. **Check Structure First**: Use get_structure() to understand content before processing\n2. **Respect Token Limits**: Always check count_tokens() before llm_query()\n3. **Use Safe Fetching**: Prefer get_units_safe() over manual chunking\n4. **Process Iteratively**: Fetch and process units in batches that fit the budget\n5. **Call set_result()**: Always call set_result() with your final answer\n\n## PERFORMANCE: Use Parallel Processing!\n\n**CRITICAL**: Use `llm_query_batch()` instead of multiple `llm_query()` calls when queries are independent.\n\n**SLOW** (sequential - each call waits for the previous):\n```python\nresults = []\nfor chunk in chunks:\n result = llm_query(\"Analyze\", chunk) # Waits for response\n results.append(result)\n```\n\n**FAST** (parallel - all calls run simultaneously):\n```python\nqueries = [(\"Analyze\", chunk) for chunk in chunks]\nresults = llm_query_batch(queries) # All run in parallel!\n```\n\nThis can provide 5-10x speedup for multi-batch processing!\n\n## Example Patterns\n\n### Small Context (< 500K chars)\n```python\nif len(context) < 400000: # Leave buffer for query\n result = llm_query(\"Answer the question\", \"context\")\n set_result(result)\n```\n\n### Codebase Analysis (FAST - using parallel batch)\n```python\n# Get structure without loading full content\nstructure = get_structure()\nprint(f\"Codebase: {structure['total_files']} files, {structure['total_tokens']} tokens\")\n\n# Get relevant files\npy_files = list_units('.py')\nunit_ids = [f['id'] for f in py_files]\n\n# Fetch in batches that fit llm_query() limit\nbatches = []\nremaining = unit_ids\nwhile remaining:\n content, remaining = get_units_safe(remaining, max_tokens=100000)\n if content:\n batches.append(content)\n\n# PARALLEL: Process all batches at once (MUCH faster than sequential!)\nqueries = [(f\"Analyze batch {i+1} of Python files\", batch) for i, batch in enumerate(batches)]\nresults = llm_query_batch(queries) # All batches processed in parallel!\n\n# Synthesize\ncombined = \"\\n\\n\".join(results)\nfinal = llm_query(\"Synthesize the analysis\", combined)\nset_result(final)\n```\n\n### Generic Large Content\n```python\nstructure = get_structure()\nall_ids = [u['id'] for u in structure['units']]\n\nresults = []\nremaining = all_ids\nwhile remaining:\n content, remaining = get_units_safe(remaining, max_tokens=100000)\n result = llm_query(\"Analyze this section\", content)\n results.append(result)\n\ncombined = \"\\n\\n\".join(results)\nfinal = llm_query(\"Provide a complete synthesis\", combined)\nset_result(final)\n```\n\n## Current Task\n\n{query}\n\nWrite Python code to accomplish this task. Your code will be executed in a sandboxed environment.";
|
|
5
5
|
/**
|
|
6
6
|
* Format the system prompt with context variables and query
|
|
7
7
|
*/
|
|
@@ -9,4 +9,17 @@ export declare function formatSystemPrompt(contextVariables: readonly {
|
|
|
9
9
|
name: string;
|
|
10
10
|
sizeHint: string;
|
|
11
11
|
}[], query: string): string;
|
|
12
|
+
/**
|
|
13
|
+
* Direct answer prompt for recursive calls (depth > 0)
|
|
14
|
+
*
|
|
15
|
+
* Unlike the main RLM prompt which asks the LLM to write Python code,
|
|
16
|
+
* this prompt asks the LLM to provide a direct text answer.
|
|
17
|
+
* This matches the MIT paper's intended behavior where sub-queries
|
|
18
|
+
* return text answers rather than generating more code.
|
|
19
|
+
*/
|
|
20
|
+
export declare const DIRECT_ANSWER_PROMPT = "You are a sub-agent analyzing content provided by a parent RLM (Recursive Language Model) agent.\n\n## Your Role\n\nYou are being called via llm_query() from a parent agent that is processing a larger context.\nYour job is to provide a DIRECT TEXT ANSWER - do NOT write Python code.\n\n## Instructions\n\n1. Read and analyze the context provided below\n2. Answer the question/task directly and thoroughly\n3. Your response will be returned as a string to the parent agent\n4. Focus on extracting and synthesizing the relevant information\n\n## Context Information\n\n{context_hint}\n\n## Task\n\n{query}\n\n## Response Format\n\nRespond with your analysis as plain text. Be comprehensive but concise.\nDo NOT wrap your response in code blocks or markdown formatting unless specifically requested.\nDo NOT write Python code - just provide the answer directly.";
|
|
21
|
+
/**
|
|
22
|
+
* Format the direct answer prompt for recursive calls
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatDirectAnswerPrompt(contextHint: string, query: string): string;
|
|
12
25
|
//# sourceMappingURL=system-prompt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/llm/prompts/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/llm/prompts/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,iBAAiB,6xMA2KoE,CAAC;AAEnG;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,gBAAgB,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAAE,EAC/D,KAAK,EAAE,MAAM,GACZ,MAAM,CAQR;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,+1BA0B4B,CAAC;AAE9D;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,GACZ,MAAM,CAIR"}
|
|
@@ -3,78 +3,169 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const RLM_SYSTEM_PROMPT = `You are an RLM (Recursive Language Model) agent. Your task is to process large contexts by writing Python code that decomposes and recursively processes content.
|
|
5
5
|
|
|
6
|
-
##
|
|
6
|
+
## Token Budget (CRITICAL)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Your token budget per llm_query() call is approximately **125,000 tokens** (~500,000 characters).
|
|
9
|
+
NEVER pass more than 500,000 characters to llm_query() - it will fail with a capacity error.
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
-
|
|
13
|
-
- context_vars: Variable names (strings) containing context to include
|
|
14
|
-
- Returns: The LLM's response as a string
|
|
11
|
+
Use these functions to stay within limits:
|
|
12
|
+
- \`count_tokens(text)\` - Check token count before calling llm_query()
|
|
13
|
+
- \`get_units_safe(ids, max_tokens)\` - Automatically fetch units within budget
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
\`\`\`python
|
|
18
|
-
# Query with full context
|
|
19
|
-
result = llm_query("Summarize the main points", "context")
|
|
15
|
+
## CRITICAL: Examine Context First (Before Decomposing)
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
chunk = context[:10000]
|
|
23
|
-
result = llm_query("What are the key findings?", chunk)
|
|
24
|
-
\`\`\`
|
|
17
|
+
Before deciding how to process the context, you MUST examine it:
|
|
25
18
|
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
1. **Check size and structure**:
|
|
20
|
+
\`\`\`python
|
|
21
|
+
print(f"Context: {len(context)} chars, ~{len(context)//4} tokens")
|
|
22
|
+
print(context[:2000]) # See the beginning
|
|
23
|
+
\`\`\`
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
\`\`\`python
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
2. **Scan for patterns** relevant to the query:
|
|
26
|
+
\`\`\`python
|
|
27
|
+
import re
|
|
28
|
+
# Find sections that might contain the answer
|
|
29
|
+
matches = re.findall(r'relevant_pattern', context)
|
|
30
|
+
print(f"Found {len(matches)} potentially relevant sections")
|
|
31
|
+
\`\`\`
|
|
33
32
|
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
3. **THEN decide** how to decompose:
|
|
34
|
+
- Small context? Process directly
|
|
35
|
+
- Found specific matches? Focus on those
|
|
36
|
+
- Large, unfocused? Chunk strategically
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
Do NOT blindly iterate through all content. Use your judgment to filter and prioritize.
|
|
39
|
+
|
|
40
|
+
## Available Python Functions
|
|
41
|
+
|
|
42
|
+
**ONLY USE THESE EXACT FUNCTION NAMES** - any other function will cause "name not defined" error.
|
|
43
|
+
|
|
44
|
+
### Core Functions
|
|
45
|
+
- \`llm_query(query: str, *context_vars) -> str\` - Make recursive LLM call (max 500K chars)
|
|
46
|
+
- \`llm_query_batch(queries: list[tuple[str, str]]) -> list[str]\` - **PARALLEL** LLM calls (MUCH faster!)
|
|
47
|
+
- \`set_result(result: str) -> None\` - Set final answer
|
|
48
|
+
- \`set_result_final(result: str, confidence: float = 1.0) -> None\` - Set final answer with early termination
|
|
49
|
+
- \`set_variable(name: str, value: str) -> None\` - Store a variable
|
|
50
|
+
|
|
51
|
+
### Structure Functions (for codebase with "=== FILE:" markers)
|
|
52
|
+
- \`get_structure() -> dict\` - Returns {type, total_files, units: [{id, path, tokens}]}
|
|
53
|
+
- \`get_unit(unit_id: str) -> str\` - Get specific unit content
|
|
54
|
+
- \`list_units(pattern: str = None) -> list[dict]\` - List units matching pattern
|
|
55
|
+
- \`get_units_safe(unit_ids: list, max_tokens: int = 50000) -> tuple[str, list]\` - Fetch units within budget
|
|
56
|
+
|
|
57
|
+
### Utility Functions
|
|
58
|
+
- \`count_tokens(text: str) -> int\` - Estimate tokens (~4 chars/token)
|
|
59
|
+
- \`chunk_text(text: str, chunk_size: int = 10000, overlap: int = 500) -> list[str]\` - Split text
|
|
60
|
+
- \`filter_lines(text: str, predicate: str) -> str\` - Filter lines containing predicate
|
|
61
|
+
|
|
62
|
+
**WRONG NAMES (will error):** get_repo_structure, get_file_list, list_files, get_units, get_repo_info
|
|
41
63
|
|
|
42
64
|
## Available Context Variables
|
|
43
65
|
|
|
44
|
-
|
|
66
|
+
**CRITICAL: Your code runs in a FRESH, ISOLATED Python environment.**
|
|
67
|
+
The ONLY variables available to you are:
|
|
68
|
+
|
|
45
69
|
{context_variables}
|
|
46
70
|
|
|
71
|
+
**DO NOT** reference any other variables - they will cause "name not defined" errors.
|
|
72
|
+
|
|
73
|
+
## When to Use Which Approach
|
|
74
|
+
|
|
75
|
+
**If context is SMALL (< 100K tokens / 400K chars):**
|
|
76
|
+
- Just examine the content directly with \`print(context[:5000])\`
|
|
77
|
+
- Answer the question with \`set_result("your answer")\`
|
|
78
|
+
- NO need for structure extraction or llm_query()
|
|
79
|
+
|
|
80
|
+
**If context is LARGE and has structure (contains "=== FILE:" markers):**
|
|
81
|
+
- Use \`get_structure()\` to understand the structure
|
|
82
|
+
- Use \`get_units_safe()\` to fetch portions
|
|
83
|
+
- Use \`llm_query()\` to analyze each portion
|
|
84
|
+
|
|
85
|
+
**If context is LARGE but unstructured:**
|
|
86
|
+
- Use \`chunk_text()\` to split into pieces
|
|
87
|
+
- Use \`llm_query()\` on each chunk
|
|
88
|
+
|
|
47
89
|
## Guidelines
|
|
48
90
|
|
|
49
|
-
1. **
|
|
50
|
-
2. **
|
|
51
|
-
3. **
|
|
52
|
-
4. **
|
|
91
|
+
1. **Check Structure First**: Use get_structure() to understand content before processing
|
|
92
|
+
2. **Respect Token Limits**: Always check count_tokens() before llm_query()
|
|
93
|
+
3. **Use Safe Fetching**: Prefer get_units_safe() over manual chunking
|
|
94
|
+
4. **Process Iteratively**: Fetch and process units in batches that fit the budget
|
|
53
95
|
5. **Call set_result()**: Always call set_result() with your final answer
|
|
54
96
|
|
|
55
|
-
##
|
|
97
|
+
## PERFORMANCE: Use Parallel Processing!
|
|
98
|
+
|
|
99
|
+
**CRITICAL**: Use \`llm_query_batch()\` instead of multiple \`llm_query()\` calls when queries are independent.
|
|
100
|
+
|
|
101
|
+
**SLOW** (sequential - each call waits for the previous):
|
|
102
|
+
\`\`\`python
|
|
103
|
+
results = []
|
|
104
|
+
for chunk in chunks:
|
|
105
|
+
result = llm_query("Analyze", chunk) # Waits for response
|
|
106
|
+
results.append(result)
|
|
107
|
+
\`\`\`
|
|
108
|
+
|
|
109
|
+
**FAST** (parallel - all calls run simultaneously):
|
|
110
|
+
\`\`\`python
|
|
111
|
+
queries = [("Analyze", chunk) for chunk in chunks]
|
|
112
|
+
results = llm_query_batch(queries) # All run in parallel!
|
|
113
|
+
\`\`\`
|
|
114
|
+
|
|
115
|
+
This can provide 5-10x speedup for multi-batch processing!
|
|
56
116
|
|
|
117
|
+
## Example Patterns
|
|
118
|
+
|
|
119
|
+
### Small Context (< 500K chars)
|
|
57
120
|
\`\`\`python
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
result = llm_query("Answer the question based on this context", "context")
|
|
121
|
+
if len(context) < 400000: # Leave buffer for query
|
|
122
|
+
result = llm_query("Answer the question", "context")
|
|
61
123
|
set_result(result)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
124
|
+
\`\`\`
|
|
125
|
+
|
|
126
|
+
### Codebase Analysis (FAST - using parallel batch)
|
|
127
|
+
\`\`\`python
|
|
128
|
+
# Get structure without loading full content
|
|
129
|
+
structure = get_structure()
|
|
130
|
+
print(f"Codebase: {structure['total_files']} files, {structure['total_tokens']} tokens")
|
|
131
|
+
|
|
132
|
+
# Get relevant files
|
|
133
|
+
py_files = list_units('.py')
|
|
134
|
+
unit_ids = [f['id'] for f in py_files]
|
|
135
|
+
|
|
136
|
+
# Fetch in batches that fit llm_query() limit
|
|
137
|
+
batches = []
|
|
138
|
+
remaining = unit_ids
|
|
139
|
+
while remaining:
|
|
140
|
+
content, remaining = get_units_safe(remaining, max_tokens=100000)
|
|
141
|
+
if content:
|
|
142
|
+
batches.append(content)
|
|
143
|
+
|
|
144
|
+
# PARALLEL: Process all batches at once (MUCH faster than sequential!)
|
|
145
|
+
queries = [(f"Analyze batch {i+1} of Python files", batch) for i, batch in enumerate(batches)]
|
|
146
|
+
results = llm_query_batch(queries) # All batches processed in parallel!
|
|
147
|
+
|
|
148
|
+
# Synthesize
|
|
149
|
+
combined = "\\n\\n".join(results)
|
|
150
|
+
final = llm_query("Synthesize the analysis", combined)
|
|
151
|
+
set_result(final)
|
|
152
|
+
\`\`\`
|
|
153
|
+
|
|
154
|
+
### Generic Large Content
|
|
155
|
+
\`\`\`python
|
|
156
|
+
structure = get_structure()
|
|
157
|
+
all_ids = [u['id'] for u in structure['units']]
|
|
158
|
+
|
|
159
|
+
results = []
|
|
160
|
+
remaining = all_ids
|
|
161
|
+
while remaining:
|
|
162
|
+
content, remaining = get_units_safe(remaining, max_tokens=100000)
|
|
163
|
+
result = llm_query("Analyze this section", content)
|
|
164
|
+
results.append(result)
|
|
165
|
+
|
|
166
|
+
combined = "\\n\\n".join(results)
|
|
167
|
+
final = llm_query("Provide a complete synthesis", combined)
|
|
168
|
+
set_result(final)
|
|
78
169
|
\`\`\`
|
|
79
170
|
|
|
80
171
|
## Current Task
|
|
@@ -93,4 +184,47 @@ export function formatSystemPrompt(contextVariables, query) {
|
|
|
93
184
|
.replace('{context_variables}', varList || '(none)')
|
|
94
185
|
.replace('{query}', query);
|
|
95
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Direct answer prompt for recursive calls (depth > 0)
|
|
189
|
+
*
|
|
190
|
+
* Unlike the main RLM prompt which asks the LLM to write Python code,
|
|
191
|
+
* this prompt asks the LLM to provide a direct text answer.
|
|
192
|
+
* This matches the MIT paper's intended behavior where sub-queries
|
|
193
|
+
* return text answers rather than generating more code.
|
|
194
|
+
*/
|
|
195
|
+
export const DIRECT_ANSWER_PROMPT = `You are a sub-agent analyzing content provided by a parent RLM (Recursive Language Model) agent.
|
|
196
|
+
|
|
197
|
+
## Your Role
|
|
198
|
+
|
|
199
|
+
You are being called via llm_query() from a parent agent that is processing a larger context.
|
|
200
|
+
Your job is to provide a DIRECT TEXT ANSWER - do NOT write Python code.
|
|
201
|
+
|
|
202
|
+
## Instructions
|
|
203
|
+
|
|
204
|
+
1. Read and analyze the context provided below
|
|
205
|
+
2. Answer the question/task directly and thoroughly
|
|
206
|
+
3. Your response will be returned as a string to the parent agent
|
|
207
|
+
4. Focus on extracting and synthesizing the relevant information
|
|
208
|
+
|
|
209
|
+
## Context Information
|
|
210
|
+
|
|
211
|
+
{context_hint}
|
|
212
|
+
|
|
213
|
+
## Task
|
|
214
|
+
|
|
215
|
+
{query}
|
|
216
|
+
|
|
217
|
+
## Response Format
|
|
218
|
+
|
|
219
|
+
Respond with your analysis as plain text. Be comprehensive but concise.
|
|
220
|
+
Do NOT wrap your response in code blocks or markdown formatting unless specifically requested.
|
|
221
|
+
Do NOT write Python code - just provide the answer directly.`;
|
|
222
|
+
/**
|
|
223
|
+
* Format the direct answer prompt for recursive calls
|
|
224
|
+
*/
|
|
225
|
+
export function formatDirectAnswerPrompt(contextHint, query) {
|
|
226
|
+
return DIRECT_ANSWER_PROMPT
|
|
227
|
+
.replace('{context_hint}', contextHint)
|
|
228
|
+
.replace('{query}', query);
|
|
229
|
+
}
|
|
96
230
|
//# sourceMappingURL=system-prompt.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../../../src/infrastructure/llm/prompts/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG
|
|
1
|
+
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../../../src/infrastructure/llm/prompts/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kGA2KiE,CAAC;AAEnG;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,gBAA+D,EAC/D,KAAa;IAEb,MAAM,OAAO,GAAG,gBAAgB;SAC7B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC;SAC5C,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,iBAAiB;SACrB,OAAO,CAAC,qBAAqB,EAAE,OAAO,IAAI,QAAQ,CAAC;SACnD,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;6DA0ByB,CAAC;AAE9D;;GAEG;AACH,MAAM,UAAU,wBAAwB,CACtC,WAAmB,EACnB,KAAa;IAEb,OAAO,oBAAoB;SACxB,OAAO,CAAC,gBAAgB,EAAE,WAAW,CAAC;SACtC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug Logger Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides consistent debug logging across the RLM codebase.
|
|
5
|
+
* Only logs when DEBUG_RLM environment variable is set.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Debug log level prefixes
|
|
9
|
+
*/
|
|
10
|
+
export type LogPrefix = 'QH' | 'LQH' | 'LLM' | 'PE' | 'PM' | 'RLM' | 'SM';
|
|
11
|
+
/**
|
|
12
|
+
* Creates a debug logger with a specific prefix.
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const dbg = createDebugLogger('QH');
|
|
17
|
+
* dbg('EXECUTE_START', { session: '123', depth: 0 });
|
|
18
|
+
* // Output: [12:34:56.789] QH: EXECUTE_START {"session":"123","depth":0}
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @param prefix - Short identifier for the component (e.g., 'QH' for QueryHandler)
|
|
22
|
+
* @returns Debug logging function that only logs when DEBUG_RLM is set
|
|
23
|
+
*/
|
|
24
|
+
export declare function createDebugLogger(prefix: LogPrefix): (msg: string, data?: unknown) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Check if debug mode is enabled
|
|
27
|
+
*/
|
|
28
|
+
export declare function isDebugEnabled(): boolean;
|
|
29
|
+
//# sourceMappingURL=debug-logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-logger.d.ts","sourceRoot":"","sources":["../../../src/infrastructure/logging/debug-logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,MAAM,SAAS,GACjB,IAAI,GACJ,KAAK,GACL,KAAK,GACL,IAAI,GACJ,IAAI,GACJ,KAAK,GACL,IAAI,CAAC;AAET;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,SAAS,GAChB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,KAAK,IAAI,CAQvC;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAExC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug Logger Utility
|
|
3
|
+
*
|
|
4
|
+
* Provides consistent debug logging across the RLM codebase.
|
|
5
|
+
* Only logs when DEBUG_RLM environment variable is set.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Creates a debug logger with a specific prefix.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const dbg = createDebugLogger('QH');
|
|
13
|
+
* dbg('EXECUTE_START', { session: '123', depth: 0 });
|
|
14
|
+
* // Output: [12:34:56.789] QH: EXECUTE_START {"session":"123","depth":0}
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @param prefix - Short identifier for the component (e.g., 'QH' for QueryHandler)
|
|
18
|
+
* @returns Debug logging function that only logs when DEBUG_RLM is set
|
|
19
|
+
*/
|
|
20
|
+
export function createDebugLogger(prefix) {
|
|
21
|
+
return (msg, data) => {
|
|
22
|
+
if (!process.env['DEBUG_RLM'])
|
|
23
|
+
return;
|
|
24
|
+
const ts = new Date().toISOString().slice(11, 23);
|
|
25
|
+
const dataStr = data !== undefined ? JSON.stringify(data) : '';
|
|
26
|
+
console.log(`[${ts}] ${prefix}: ${msg}`, dataStr);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Check if debug mode is enabled
|
|
31
|
+
*/
|
|
32
|
+
export function isDebugEnabled() {
|
|
33
|
+
return !!process.env['DEBUG_RLM'];
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=debug-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-logger.js","sourceRoot":"","sources":["../../../src/infrastructure/logging/debug-logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAcH;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAiB;IAEjB,OAAO,CAAC,GAAW,EAAE,IAAc,EAAE,EAAE;QACrC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;YAAE,OAAO;QAEtC,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,MAAM,KAAK,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc;IAC5B,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AACpC,CAAC"}
|