zrb 1.9.4__py3-none-any.whl → 1.9.6__py3-none-any.whl
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.
- zrb/__init__.py +8 -8
- zrb/__main__.py +1 -1
- zrb/builtin/__init__.py +0 -50
- zrb/builtin/llm/chat_session.py +1 -1
- zrb/builtin/llm/history.py +1 -1
- zrb/builtin/llm/llm_ask.py +3 -3
- zrb/builtin/llm/tool/api.py +19 -9
- zrb/builtin/llm/tool/cli.py +11 -5
- zrb/builtin/llm/tool/code.py +20 -20
- zrb/builtin/llm/tool/file.py +107 -155
- zrb/builtin/llm/tool/rag.py +28 -5
- zrb/builtin/llm/tool/sub_agent.py +12 -14
- zrb/builtin/llm/tool/web.py +46 -14
- zrb/builtin/todo.py +1 -1
- zrb/{llm_config.py → config/llm_config.py} +143 -158
- zrb/{llm_rate_limitter.py → config/llm_rate_limitter.py} +1 -1
- zrb/{runner → config}/web_auth_config.py +1 -1
- zrb/context/shared_context.py +1 -1
- zrb/input/text_input.py +1 -1
- zrb/runner/cli.py +2 -2
- zrb/runner/web_app.py +2 -2
- zrb/runner/web_route/docs_route.py +1 -1
- zrb/runner/web_route/error_page/serve_default_404.py +1 -1
- zrb/runner/web_route/error_page/show_error_page.py +1 -1
- zrb/runner/web_route/home_page/home_page_route.py +2 -2
- zrb/runner/web_route/login_api_route.py +1 -1
- zrb/runner/web_route/login_page/login_page_route.py +2 -2
- zrb/runner/web_route/logout_api_route.py +1 -1
- zrb/runner/web_route/logout_page/logout_page_route.py +2 -2
- zrb/runner/web_route/node_page/group/show_group_page.py +1 -1
- zrb/runner/web_route/node_page/node_page_route.py +1 -1
- zrb/runner/web_route/node_page/task/show_task_page.py +1 -1
- zrb/runner/web_route/refresh_token_api_route.py +1 -1
- zrb/runner/web_route/static/static_route.py +1 -1
- zrb/runner/web_route/task_input_api_route.py +1 -1
- zrb/runner/web_route/task_session_api_route.py +1 -1
- zrb/runner/web_util/cookie.py +1 -1
- zrb/runner/web_util/token.py +1 -1
- zrb/runner/web_util/user.py +1 -1
- zrb/session_state_logger/session_state_logger_factory.py +1 -1
- zrb/task/cmd_task.py +1 -1
- zrb/task/llm/agent.py +1 -1
- zrb/task/llm/config.py +1 -1
- zrb/task/llm/context_enrichment.py +2 -2
- zrb/task/llm/history_summarization.py +2 -2
- zrb/task/llm/prompt.py +1 -1
- zrb/task/llm_task.py +1 -1
- zrb/util/init_path.py +1 -1
- zrb-1.9.6.dist-info/METADATA +250 -0
- {zrb-1.9.4.dist-info → zrb-1.9.6.dist-info}/RECORD +53 -53
- zrb-1.9.4.dist-info/METADATA +0 -245
- /zrb/{config.py → config/config.py} +0 -0
- {zrb-1.9.4.dist-info → zrb-1.9.6.dist-info}/WHEEL +0 -0
- {zrb-1.9.4.dist-info → zrb-1.9.6.dist-info}/entry_points.txt +0 -0
zrb/builtin/llm/tool/file.py
CHANGED
@@ -5,8 +5,8 @@ import re
|
|
5
5
|
from typing import Any, Dict, List, Optional
|
6
6
|
|
7
7
|
from zrb.builtin.llm.tool.sub_agent import create_sub_agent_tool
|
8
|
+
from zrb.config.llm_rate_limitter import llm_rate_limitter
|
8
9
|
from zrb.context.any_context import AnyContext
|
9
|
-
from zrb.llm_rate_limitter import llm_rate_limitter
|
10
10
|
from zrb.util.file import read_file, read_file_with_line_numbers, write_file
|
11
11
|
|
12
12
|
_EXTRACT_INFO_FROM_FILE_SYSTEM_PROMPT = """
|
@@ -106,17 +106,22 @@ def list_files(
|
|
106
106
|
include_hidden: bool = False,
|
107
107
|
excluded_patterns: Optional[list[str]] = None,
|
108
108
|
) -> str:
|
109
|
-
"""
|
109
|
+
"""
|
110
|
+
Lists the files and directories within a specified path.
|
111
|
+
|
112
|
+
This is a fundamental tool for exploring the file system. Use it to discover the structure of a directory, find specific files, or get a general overview of the project layout before performing other operations.
|
113
|
+
|
110
114
|
Args:
|
111
|
-
path (str):
|
112
|
-
recursive (bool):
|
113
|
-
include_hidden (bool):
|
114
|
-
excluded_patterns (
|
115
|
-
|
115
|
+
path (str, optional): The directory path to list. Defaults to the current directory (".").
|
116
|
+
recursive (bool, optional): If True, lists files and directories recursively. If False, lists only the top-level contents. Defaults to True.
|
117
|
+
include_hidden (bool, optional): If True, includes hidden files and directories (those starting with a dot). Defaults to False.
|
118
|
+
excluded_patterns (list[str], optional): A list of glob patterns to exclude from the listing. This is useful for ignoring irrelevant files like build artifacts or virtual environments. Defaults to a standard list of common exclusion patterns.
|
119
|
+
|
116
120
|
Returns:
|
117
|
-
str: JSON string
|
121
|
+
str: A JSON string containing a list of file and directory paths relative to the input path.
|
122
|
+
Example: '{"files": ["src/main.py", "README.md"]}'
|
118
123
|
Raises:
|
119
|
-
|
124
|
+
FileNotFoundError: If the specified path does not exist.
|
120
125
|
"""
|
121
126
|
all_files: list[str] = []
|
122
127
|
abs_path = os.path.abspath(os.path.expanduser(path))
|
@@ -214,19 +219,26 @@ def read_from_file(
|
|
214
219
|
start_line: Optional[int] = None,
|
215
220
|
end_line: Optional[int] = None,
|
216
221
|
) -> str:
|
217
|
-
"""
|
218
|
-
|
222
|
+
"""
|
223
|
+
Reads the content of a file, optionally from a specific start line to an end line.
|
224
|
+
|
225
|
+
This tool is essential for inspecting file contents. It can read both text and PDF files. The returned content is prefixed with line numbers, which is crucial for providing context when you need to modify the file later with the `apply_diff` tool.
|
226
|
+
|
227
|
+
Use this tool to:
|
228
|
+
- Examine the source code of a file.
|
229
|
+
- Read configuration files.
|
230
|
+
- Check the contents of a document.
|
231
|
+
|
219
232
|
Args:
|
220
|
-
path (str):
|
221
|
-
start_line (
|
222
|
-
|
223
|
-
|
224
|
-
Defaults to None (end of file).
|
233
|
+
path (str): The path to the file to read.
|
234
|
+
start_line (int, optional): The 1-based line number to start reading from. If omitted, reading starts from the beginning of the file.
|
235
|
+
end_line (int, optional): The 1-based line number to stop reading at (inclusive). If omitted, reads to the end of the file.
|
236
|
+
|
225
237
|
Returns:
|
226
|
-
str: JSON
|
227
|
-
|
238
|
+
str: A JSON object containing the file path, the requested content with line numbers, the start and end lines, and the total number of lines in the file.
|
239
|
+
Example: '{"path": "src/main.py", "content": "1: import os\n2: \n3: print(\"Hello, World!\")", "start_line": 1, "end_line": 3, "total_lines": 3}'
|
228
240
|
Raises:
|
229
|
-
|
241
|
+
FileNotFoundError: If the specified file does not exist.
|
230
242
|
"""
|
231
243
|
abs_path = os.path.abspath(os.path.expanduser(path))
|
232
244
|
# Check if file exists
|
@@ -267,26 +279,20 @@ def read_from_file(
|
|
267
279
|
def write_to_file(
|
268
280
|
path: str,
|
269
281
|
content: str,
|
270
|
-
line_count: int,
|
271
282
|
) -> str:
|
272
|
-
"""
|
283
|
+
"""
|
284
|
+
Writes content to a file, completely overwriting it if it exists or creating it if it doesn't.
|
285
|
+
|
286
|
+
Use this tool to create new files or to replace the entire content of existing files. This is a destructive operation, so be certain of your actions. Always read the file first to understand its contents before overwriting it, unless you are creating a new file.
|
287
|
+
|
273
288
|
Args:
|
274
|
-
path (str):
|
275
|
-
content (str):
|
276
|
-
|
277
|
-
line_count (int): Number of lines in the provided content.
|
289
|
+
path (str): The path to the file to write to.
|
290
|
+
content (str): The full, complete content to be written to the file. Do not use partial content or omit any lines.
|
291
|
+
|
278
292
|
Returns:
|
279
|
-
str: JSON
|
280
|
-
|
281
|
-
Exception: If an error occurs.
|
293
|
+
str: A JSON object indicating success or failure.
|
294
|
+
Example: '{"success": true, "path": "new_file.txt"}'
|
282
295
|
"""
|
283
|
-
actual_lines = len(content.splitlines())
|
284
|
-
warning = None
|
285
|
-
if actual_lines != line_count:
|
286
|
-
warning = (
|
287
|
-
f"Provided line_count ({line_count}) does not match actual "
|
288
|
-
f"content lines ({actual_lines}) for file {path}"
|
289
|
-
)
|
290
296
|
try:
|
291
297
|
abs_path = os.path.abspath(os.path.expanduser(path))
|
292
298
|
# Ensure directory exists
|
@@ -295,8 +301,6 @@ def write_to_file(
|
|
295
301
|
os.makedirs(directory, exist_ok=True)
|
296
302
|
write_file(abs_path, content)
|
297
303
|
result_data = {"success": True, "path": path}
|
298
|
-
if warning:
|
299
|
-
result_data["warning"] = warning
|
300
304
|
return json.dumps(result_data)
|
301
305
|
except (OSError, IOError) as e:
|
302
306
|
raise OSError(f"Error writing file {path}: {e}")
|
@@ -310,17 +314,21 @@ def search_files(
|
|
310
314
|
file_pattern: Optional[str] = None,
|
311
315
|
include_hidden: bool = True,
|
312
316
|
) -> str:
|
313
|
-
"""
|
317
|
+
"""
|
318
|
+
Searches for a regular expression (regex) pattern within files in a specified directory.
|
319
|
+
|
320
|
+
This tool is invaluable for finding specific code, configuration, or text across multiple files. Use it to locate function definitions, variable assignments, error messages, or any other text pattern.
|
321
|
+
|
314
322
|
Args:
|
315
|
-
path (str):
|
316
|
-
regex (str): Python
|
317
|
-
file_pattern (
|
318
|
-
|
319
|
-
|
323
|
+
path (str): The directory path to start the search from.
|
324
|
+
regex (str): The Python-compatible regular expression pattern to search for.
|
325
|
+
file_pattern (str, optional): A glob pattern to filter which files get searched (e.g., "*.py", "*.md"). If omitted, all files are searched.
|
326
|
+
include_hidden (bool, optional): If True, the search will include hidden files and directories. Defaults to True.
|
327
|
+
|
320
328
|
Returns:
|
321
|
-
str: JSON
|
329
|
+
str: A JSON object containing a summary of the search and a list of results. Each result includes the file path and a list of matches, with each match showing the line number, line content, and a few lines of context from before and after the match.
|
322
330
|
Raises:
|
323
|
-
|
331
|
+
ValueError: If the provided `regex` pattern is invalid.
|
324
332
|
"""
|
325
333
|
try:
|
326
334
|
pattern = re.compile(regex)
|
@@ -407,83 +415,70 @@ def _get_file_matches(
|
|
407
415
|
raise RuntimeError(f"Unexpected error processing {file_path}: {e}")
|
408
416
|
|
409
417
|
|
410
|
-
def
|
418
|
+
def replace_in_file(
|
411
419
|
path: str,
|
412
|
-
|
413
|
-
|
414
|
-
search_content: str,
|
415
|
-
replace_content: str,
|
420
|
+
old_string: str,
|
421
|
+
new_string: str,
|
416
422
|
) -> str:
|
417
|
-
"""
|
418
|
-
|
423
|
+
"""
|
424
|
+
Replaces the first occurrence of a string in a file.
|
425
|
+
|
426
|
+
This tool is for making targeted modifications to a file. It is a single-step operation that is generally safer and more ergonomic than `write_to_file` for small changes.
|
427
|
+
|
428
|
+
To ensure the replacement is applied correctly and to avoid ambiguity, the `old_string` parameter should be a unique, multi-line string that includes context from before and after the code you want to change.
|
429
|
+
|
419
430
|
Args:
|
420
|
-
path (str):
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
line range. Must exactly match file content including whitespace/indentation,
|
425
|
-
excluding line numbers.
|
426
|
-
replace_content (str): The new content to replace the search_content with.
|
427
|
-
Excluding line numbers.
|
431
|
+
path (str): The path of the file to modify.
|
432
|
+
old_string (str): The exact, verbatim string to search for and replace. This should be a unique, multi-line block of text.
|
433
|
+
new_string (str): The new string that will replace the `old_string`.
|
434
|
+
|
428
435
|
Returns:
|
429
|
-
str: JSON
|
436
|
+
str: A JSON object indicating the success or failure of the operation.
|
430
437
|
Raises:
|
431
|
-
|
438
|
+
FileNotFoundError: If the specified file does not exist.
|
439
|
+
ValueError: If the `old_string` is not found in the file.
|
432
440
|
"""
|
433
441
|
abs_path = os.path.abspath(os.path.expanduser(path))
|
434
442
|
if not os.path.exists(abs_path):
|
435
443
|
raise FileNotFoundError(f"File not found: {path}")
|
436
444
|
try:
|
437
445
|
content = read_file(abs_path)
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
f"Invalid line range {start_line}-{end_line} for file with {len(lines)} lines"
|
442
|
-
)
|
443
|
-
original_content = "\n".join(lines[start_line - 1 : end_line])
|
444
|
-
if original_content != search_content:
|
445
|
-
error_message = (
|
446
|
-
f"Search content does not match file content at "
|
447
|
-
f"lines {start_line}-{end_line}.\n"
|
448
|
-
f"Expected ({len(search_content.splitlines())} lines):\n"
|
449
|
-
f"---\n{search_content}\n---\n"
|
450
|
-
f"Actual ({len(lines[start_line-1:end_line])} lines):\n"
|
451
|
-
f"---\n{original_content}\n---"
|
452
|
-
)
|
453
|
-
return json.dumps({"success": False, "path": path, "error": error_message})
|
454
|
-
new_lines = (
|
455
|
-
lines[: start_line - 1] + replace_content.splitlines() + lines[end_line:]
|
456
|
-
)
|
457
|
-
new_content = "\n".join(new_lines)
|
458
|
-
if content.endswith("\n"):
|
459
|
-
new_content += "\n"
|
446
|
+
if old_string not in content:
|
447
|
+
raise ValueError(f"old_string not found in file: {path}")
|
448
|
+
new_content = content.replace(old_string, new_string, 1)
|
460
449
|
write_file(abs_path, new_content)
|
461
450
|
return json.dumps({"success": True, "path": path})
|
462
451
|
except ValueError as e:
|
463
|
-
raise
|
452
|
+
raise e
|
464
453
|
except (OSError, IOError) as e:
|
465
|
-
raise OSError(f"Error applying
|
454
|
+
raise OSError(f"Error applying replacement to {path}: {e}")
|
466
455
|
except Exception as e:
|
467
|
-
raise RuntimeError(f"Unexpected error applying
|
456
|
+
raise RuntimeError(f"Unexpected error applying replacement to {path}: {e}")
|
468
457
|
|
469
458
|
|
470
459
|
async def analyze_file(
|
471
460
|
ctx: AnyContext, path: str, query: str, token_limit: int = 40000
|
472
461
|
) -> str:
|
473
|
-
"""
|
474
|
-
|
475
|
-
|
476
|
-
-
|
477
|
-
|
478
|
-
|
462
|
+
"""
|
463
|
+
Performs a deep, goal-oriented analysis of a single file using a sub-agent.
|
464
|
+
|
465
|
+
This tool is ideal for complex questions about a single file that go beyond simple reading or searching. It uses a specialized sub-agent to analyze the file's content in relation to a specific query.
|
466
|
+
|
467
|
+
Use this tool to:
|
468
|
+
- Summarize the purpose and functionality of a script or configuration file.
|
469
|
+
- Extract the structure of a file (e.g., "List all the function names in this Python file").
|
470
|
+
- Perform a detailed code review of a specific file.
|
471
|
+
- Answer complex questions like, "How is the 'User' class used in this file?".
|
472
|
+
|
479
473
|
Args:
|
480
|
-
path (str):
|
481
|
-
query(str):
|
482
|
-
token_limit(
|
474
|
+
path (str): The path to the file to be analyzed.
|
475
|
+
query (str): A clear and specific question or instruction about what to analyze in the file.
|
476
|
+
token_limit (int, optional): The maximum token length of the file content to be passed to the analysis sub-agent.
|
477
|
+
|
483
478
|
Returns:
|
484
|
-
str:
|
479
|
+
str: A detailed, markdown-formatted analysis of the file, tailored to the specified query.
|
485
480
|
Raises:
|
486
|
-
|
481
|
+
FileNotFoundError: If the specified file does not exist.
|
487
482
|
"""
|
488
483
|
abs_path = os.path.abspath(os.path.expanduser(path))
|
489
484
|
if not os.path.exists(abs_path):
|
@@ -504,38 +499,16 @@ async def analyze_file(
|
|
504
499
|
|
505
500
|
def read_many_files(paths: List[str]) -> str:
|
506
501
|
"""
|
507
|
-
|
502
|
+
Reads and returns the full content of multiple files at once.
|
508
503
|
|
509
|
-
This
|
510
|
-
several files at once. For each file path provided in the input list,
|
511
|
-
it reads the entire file content. The result is a JSON string
|
512
|
-
containing a dictionary where keys are the file paths and values are
|
513
|
-
the corresponding file contents.
|
514
|
-
|
515
|
-
Use this tool when you need a comprehensive view of multiple files,
|
516
|
-
for example, to understand how different parts of a module interact,
|
517
|
-
to check configurations across various files, or to gather context
|
518
|
-
before making widespread changes.
|
504
|
+
This tool is highly efficient for gathering context from several files simultaneously. Use it when you need to understand how different files in a project relate to each other, or when you need to inspect a set of related configuration or source code files.
|
519
505
|
|
520
506
|
Args:
|
521
|
-
paths (List[str]): A list of
|
522
|
-
files you want to read. It is crucial to
|
523
|
-
provide accurate paths. Use the `list_files`
|
524
|
-
tool if you are unsure about the exact file
|
525
|
-
locations.
|
507
|
+
paths (List[str]): A list of paths to the files you want to read. It is crucial to provide accurate paths. Use the `list_files` tool first if you are unsure about the exact file locations.
|
526
508
|
|
527
509
|
Returns:
|
528
|
-
str: A JSON
|
529
|
-
|
530
|
-
file. If a file cannot be read, its entry in the dictionary
|
531
|
-
will contain an error message.
|
532
|
-
Example:
|
533
|
-
{
|
534
|
-
"results": {
|
535
|
-
"path/to/file1.py": "...",
|
536
|
-
"path/to/file2.txt": "..."
|
537
|
-
}
|
538
|
-
}
|
510
|
+
str: A JSON object where keys are the file paths and values are their corresponding contents, prefixed with line numbers. If a file cannot be read, its value will be an error message.
|
511
|
+
Example: '{"results": {"src/api.py": "1: import ...", "config.yaml": "1: key: value"}}'
|
539
512
|
"""
|
540
513
|
results = {}
|
541
514
|
for path in paths:
|
@@ -552,42 +525,18 @@ def read_many_files(paths: List[str]) -> str:
|
|
552
525
|
|
553
526
|
def write_many_files(files: Dict[str, str]) -> str:
|
554
527
|
"""
|
555
|
-
|
556
|
-
|
557
|
-
This function allows you to create, overwrite, or update multiple
|
558
|
-
files in a single operation. You provide a dictionary where each
|
559
|
-
key is a file path and the corresponding value is the content to be
|
560
|
-
written to that file. This is particularly useful for applying
|
561
|
-
changes across a project, such as refactoring code, updating
|
562
|
-
configuration files, or creating a set of new files from a template.
|
528
|
+
Writes content to multiple files in a single, atomic operation.
|
563
529
|
|
564
|
-
|
565
|
-
file does not exist, it will be created. If it already exists, its
|
530
|
+
This tool is for applying widespread changes to a project, such as creating a set of new files from a template, updating multiple configuration files, or performing a large-scale refactoring.
|
566
531
|
|
567
|
-
|
568
|
-
Therefore, it is essential to provide the full, intended content for
|
569
|
-
each file.
|
532
|
+
Each file's content is completely replaced. If a file does not exist, it will be created. If it exists, its current content will be entirely overwritten. Therefore, you must provide the full, intended content for each file.
|
570
533
|
|
571
534
|
Args:
|
572
|
-
files (Dict[str, str]): A dictionary where keys are the file paths
|
573
|
-
(absolute or relative) and values are the
|
574
|
-
complete contents to be written to those
|
575
|
-
files.
|
535
|
+
files (Dict[str, str]): A dictionary where keys are the file paths and values are the complete contents to be written to those files.
|
576
536
|
|
577
537
|
Returns:
|
578
|
-
str: A JSON
|
579
|
-
|
580
|
-
failed, along with the corresponding error messages.
|
581
|
-
Example:
|
582
|
-
{
|
583
|
-
"success": [
|
584
|
-
"path/to/file1.py",
|
585
|
-
"path/to/file2.txt"
|
586
|
-
],
|
587
|
-
"errors": {
|
588
|
-
"path/to/problematic/file.py": "Error message"
|
589
|
-
}
|
590
|
-
}
|
538
|
+
str: A JSON object summarizing the operation, listing successfully written files and any files that failed, along with corresponding error messages.
|
539
|
+
Example: '{"success": ["file1.py", "file2.txt"], "errors": {}}'
|
591
540
|
"""
|
592
541
|
success = []
|
593
542
|
errors = {}
|
@@ -602,3 +551,6 @@ def write_many_files(files: Dict[str, str]) -> str:
|
|
602
551
|
except Exception as e:
|
603
552
|
errors[path] = f"Error writing file: {e}"
|
604
553
|
return json.dumps({"success": success, "errors": errors})
|
554
|
+
|
555
|
+
|
556
|
+
apply_diff = replace_in_file
|
zrb/builtin/llm/tool/rag.py
CHANGED
@@ -8,7 +8,7 @@ from textwrap import dedent
|
|
8
8
|
|
9
9
|
import ulid
|
10
10
|
|
11
|
-
from zrb.config import CFG
|
11
|
+
from zrb.config.config import CFG
|
12
12
|
from zrb.util.cli.style import stylize_error, stylize_faint
|
13
13
|
from zrb.util.file import read_file
|
14
14
|
|
@@ -43,10 +43,33 @@ def create_rag_from_directory(
|
|
43
43
|
openai_base_url: str | None = None,
|
44
44
|
openai_embedding_model: str | None = None,
|
45
45
|
):
|
46
|
-
"""
|
47
|
-
|
48
|
-
|
49
|
-
|
46
|
+
"""
|
47
|
+
Creates a powerful Retrieval-Augmented Generation (RAG) tool for querying a local knowledge base.
|
48
|
+
|
49
|
+
This factory function generates a tool that can perform semantic searches over a directory of documents. It automatically indexes the documents into a vector database, keeping it updated as files change. The generated tool is ideal for answering questions based on a specific set of documents, such as project documentation, research papers, or internal wikis.
|
50
|
+
|
51
|
+
The created tool will:
|
52
|
+
1. Monitor a specified directory for file changes.
|
53
|
+
2. Automatically update a vector database (ChromaDB) with the latest content.
|
54
|
+
3. Accept a user query, embed it, and perform a similarity search against the document vectors.
|
55
|
+
4. Return the most relevant document chunks that match the query.
|
56
|
+
|
57
|
+
Args:
|
58
|
+
tool_name (str): The name for the generated RAG tool (e.g., "search_project_docs").
|
59
|
+
tool_description (str): A clear description of what the generated tool does and when to use it (e.g., "Searches the project's technical documentation to answer questions.").
|
60
|
+
document_dir_path (str, optional): The path to the directory containing the documents to be indexed.
|
61
|
+
vector_db_path (str, optional): The path to store the ChromaDB vector database.
|
62
|
+
vector_db_collection (str, optional): The name of the collection within the vector database.
|
63
|
+
chunk_size (int, optional): The size of text chunks for embedding.
|
64
|
+
overlap (int, optional): The overlap between text chunks.
|
65
|
+
max_result_count (int, optional): The maximum number of search results to return.
|
66
|
+
file_reader (list[RAGFileReader], optional): Custom file readers for specific file types.
|
67
|
+
openai_api_key (str, optional): OpenAI API key for embeddings.
|
68
|
+
openai_base_url (str, optional): OpenAI base URL for embeddings.
|
69
|
+
openai_embedding_model (str, optional): The embedding model to use.
|
70
|
+
|
71
|
+
Returns:
|
72
|
+
Callable: An asynchronous function that serves as the RAG tool.
|
50
73
|
"""
|
51
74
|
|
52
75
|
async def retrieve(query: str) -> str:
|
@@ -29,25 +29,23 @@ def create_sub_agent_tool(
|
|
29
29
|
mcp_servers: list["MCPServer"] = [],
|
30
30
|
) -> Callable[[AnyContext, str], Coroutine[Any, Any, str]]:
|
31
31
|
"""
|
32
|
-
|
32
|
+
Creates a "tool that is another AI agent," capable of handling complex, multi-step sub-tasks.
|
33
33
|
|
34
|
-
This factory
|
35
|
-
|
36
|
-
|
34
|
+
This powerful factory function generates a tool that, when used, spins up a temporary, specialized AI agent. This "sub-agent" has its own system prompt, tools, and context, allowing it to focus exclusively on accomplishing the task it's given without being distracted by the main conversation.
|
35
|
+
|
36
|
+
This is ideal for delegating complex tasks like analyzing a file or a repository.
|
37
37
|
|
38
38
|
Args:
|
39
|
-
tool_name: The name
|
40
|
-
tool_description:
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
sub_agent_mcp_servers: A list of MCP servers for the sub-agent (optional).
|
39
|
+
tool_name (str): The name for the generated sub-agent tool.
|
40
|
+
tool_description (str): A clear description of the sub-agent's purpose and when to use it.
|
41
|
+
system_prompt (str, optional): The system prompt that will guide the sub-agent's behavior.
|
42
|
+
model (str | Model, optional): The language model the sub-agent will use.
|
43
|
+
model_settings (ModelSettings, optional): Specific settings for the sub-agent's model.
|
44
|
+
tools (list, optional): A list of tools that will be exclusively available to the sub-agent.
|
45
|
+
mcp_servers (list, optional): A list of MCP servers for the sub-agent.
|
47
46
|
|
48
47
|
Returns:
|
49
|
-
An
|
50
|
-
runs the sub-agent, and returns the sub-agent's final message content.
|
48
|
+
Callable: An asynchronous function that serves as the sub-agent tool. When called, it runs the sub-agent with a given query and returns its final result.
|
51
49
|
"""
|
52
50
|
|
53
51
|
async def run_sub_agent(ctx: AnyContext, query: str) -> str:
|
zrb/builtin/llm/tool/web.py
CHANGED
@@ -3,11 +3,16 @@ from collections.abc import Callable
|
|
3
3
|
|
4
4
|
|
5
5
|
async def open_web_page(url: str) -> str:
|
6
|
-
"""
|
6
|
+
"""
|
7
|
+
Fetches and parses the textual content of a given web page URL.
|
8
|
+
|
9
|
+
Use this tool to "read" a web page. It strips away HTML tags, scripts, and other non-textual elements to provide the clean text content. It also extracts any hyperlinks found on the page. This is useful when you need to understand the content of a specific URL that you have discovered through a search or from another source.
|
10
|
+
|
7
11
|
Args:
|
8
|
-
url (str): The URL of the web page to open.
|
12
|
+
url (str): The full URL of the web page to open (e.g., "https://example.com/article").
|
13
|
+
|
9
14
|
Returns:
|
10
|
-
str: JSON
|
15
|
+
str: A JSON object containing the cleaned text `content` of the page and a list of `links_on_page`.
|
11
16
|
"""
|
12
17
|
|
13
18
|
async def get_page_content(page_url: str):
|
@@ -57,13 +62,30 @@ async def open_web_page(url: str) -> str:
|
|
57
62
|
|
58
63
|
|
59
64
|
def create_search_internet_tool(serp_api_key: str) -> Callable[[str, int], str]:
|
65
|
+
"""
|
66
|
+
Creates a tool that searches the internet using the SerpAPI Google Search API.
|
67
|
+
|
68
|
+
This factory returns a function that can be used to find information on the web. The generated tool is the primary way to answer general knowledge questions or to find information on topics you are unfamiliar with.
|
69
|
+
|
70
|
+
Args:
|
71
|
+
serp_api_key (str): The API key for SerpAPI.
|
72
|
+
|
73
|
+
Returns:
|
74
|
+
Callable: A function that takes a search query and returns a list of search results.
|
75
|
+
"""
|
76
|
+
|
60
77
|
def search_internet(query: str, num_results: int = 10) -> str:
|
61
|
-
"""
|
78
|
+
"""
|
79
|
+
Performs an internet search using Google and returns a summary of the results.
|
80
|
+
|
81
|
+
Use this tool to find information on the web, answer general knowledge questions, or research topics.
|
82
|
+
|
62
83
|
Args:
|
63
|
-
query (str):
|
64
|
-
num_results (int):
|
84
|
+
query (str): The search query.
|
85
|
+
num_results (int, optional): The desired number of search results. Defaults to 10.
|
86
|
+
|
65
87
|
Returns:
|
66
|
-
str: JSON
|
88
|
+
str: A JSON object containing the parsed text content from the search results page.
|
67
89
|
"""
|
68
90
|
import requests
|
69
91
|
|
@@ -90,11 +112,16 @@ def create_search_internet_tool(serp_api_key: str) -> Callable[[str, int], str]:
|
|
90
112
|
|
91
113
|
|
92
114
|
def search_wikipedia(query: str) -> str:
|
93
|
-
"""
|
115
|
+
"""
|
116
|
+
Searches for articles on Wikipedia.
|
117
|
+
|
118
|
+
This is a specialized search tool for querying Wikipedia. It's best for when the user is asking for definitions, historical information, or biographical details that are likely to be found on an encyclopedia.
|
119
|
+
|
94
120
|
Args:
|
95
|
-
query (str):
|
121
|
+
query (str): The search term or question.
|
122
|
+
|
96
123
|
Returns:
|
97
|
-
str: JSON from Wikipedia API
|
124
|
+
str: The raw JSON response from the Wikipedia API, containing a list of search results.
|
98
125
|
"""
|
99
126
|
import requests
|
100
127
|
|
@@ -104,12 +131,17 @@ def search_wikipedia(query: str) -> str:
|
|
104
131
|
|
105
132
|
|
106
133
|
def search_arxiv(query: str, num_results: int = 10) -> str:
|
107
|
-
"""
|
134
|
+
"""
|
135
|
+
Searches for academic papers and preprints on ArXiv.
|
136
|
+
|
137
|
+
Use this tool when the user's query is scientific or technical in nature and they are likely looking for research papers, articles, or academic publications.
|
138
|
+
|
108
139
|
Args:
|
109
|
-
query (str):
|
110
|
-
num_results (int):
|
140
|
+
query (str): The search query, which can include keywords, author names, or titles.
|
141
|
+
num_results (int, optional): The maximum number of results to return. Defaults to 10.
|
142
|
+
|
111
143
|
Returns:
|
112
|
-
str: XML
|
144
|
+
str: The raw XML response from the ArXiv API, containing a list of matching papers.
|
113
145
|
"""
|
114
146
|
import requests
|
115
147
|
|
zrb/builtin/todo.py
CHANGED
@@ -4,7 +4,7 @@ import os
|
|
4
4
|
from typing import Any
|
5
5
|
|
6
6
|
from zrb.builtin.group import todo_group
|
7
|
-
from zrb.config import CFG
|
7
|
+
from zrb.config.config import CFG
|
8
8
|
from zrb.context.any_context import AnyContext
|
9
9
|
from zrb.input.str_input import StrInput
|
10
10
|
from zrb.input.text_input import TextInput
|