llmalchemy 2.0.0__tar.gz → 2.1.0__tar.gz
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.
- {llmalchemy-2.0.0 → llmalchemy-2.1.0}/PKG-INFO +1 -1
- {llmalchemy-2.0.0 → llmalchemy-2.1.0}/pyproject.toml +1 -1
- {llmalchemy-2.0.0 → llmalchemy-2.1.0}/pyproject.toml.orig +1 -1
- {llmalchemy-2.0.0 → llmalchemy-2.1.0}/src/llmalchemy/agent.py +11 -1
- {llmalchemy-2.0.0 → llmalchemy-2.1.0}/src/llmalchemy/context.py +29 -9
- {llmalchemy-2.0.0 → llmalchemy-2.1.0}/src/llmalchemy/prompt.jinja +4 -3
- {llmalchemy-2.0.0 → llmalchemy-2.1.0}/README.md +0 -0
- {llmalchemy-2.0.0 → llmalchemy-2.1.0}/src/llmalchemy/__init__.py +0 -0
- {llmalchemy-2.0.0 → llmalchemy-2.1.0}/src/llmalchemy/code.py +0 -0
- {llmalchemy-2.0.0 → llmalchemy-2.1.0}/src/llmalchemy/database.py +0 -0
- {llmalchemy-2.0.0 → llmalchemy-2.1.0}/src/llmalchemy/tools.py +0 -0
|
@@ -202,6 +202,7 @@ def run(
|
|
|
202
202
|
allowed_imports: list[str] | None = None,
|
|
203
203
|
prompt_template: str | Path | None = None,
|
|
204
204
|
output_extensions: type[BaseModel] | None = None,
|
|
205
|
+
referenceable_tables: list[str] | None = None,
|
|
205
206
|
) -> Iterator[Event]:
|
|
206
207
|
"""Execute the agentic loop.
|
|
207
208
|
|
|
@@ -223,6 +224,9 @@ def run(
|
|
|
223
224
|
- ``SYMBOLS``: used to show ageent all pre-loaded namespace symbols.
|
|
224
225
|
- ``TOOLS``: usedf to show the agent tool names + short descriptions.
|
|
225
226
|
- ``IMPORTS``: used to show the agent which modules it may import.
|
|
227
|
+
referenceable_tables: Schema table names the agent may cite inline in its
|
|
228
|
+
messages, e.g. ``[authors:1]``. Defaults to ``None`` (disabled);
|
|
229
|
+
unknown names raise ``ValueError``.
|
|
226
230
|
|
|
227
231
|
Yields:
|
|
228
232
|
``Event``: system instruction, loop signals, and conversation messages.
|
|
@@ -238,6 +242,7 @@ def run(
|
|
|
238
242
|
allowed_imports,
|
|
239
243
|
prompt_template,
|
|
240
244
|
output_extensions,
|
|
245
|
+
referenceable_tables,
|
|
241
246
|
)
|
|
242
247
|
|
|
243
248
|
|
|
@@ -251,6 +256,7 @@ def _run(
|
|
|
251
256
|
allowed_imports: list[str] | None,
|
|
252
257
|
prompt_template: str | Path | None,
|
|
253
258
|
output_extensions: type[BaseModel] | None,
|
|
259
|
+
referenceable_tables: list[str] | None = None,
|
|
254
260
|
) -> Iterator[Event]:
|
|
255
261
|
"""Agentic loop body (see :func:`run`)."""
|
|
256
262
|
# Initialize everything
|
|
@@ -258,7 +264,9 @@ def _run(
|
|
|
258
264
|
allowed_imports = ["sqlalchemy"] if allowed_imports is None else allowed_imports
|
|
259
265
|
output_schema = _build_output_schema(output_extensions)
|
|
260
266
|
namespace, descriptions = _init_namespace(session, base, tools)
|
|
261
|
-
system_instruction = render(
|
|
267
|
+
system_instruction = render(
|
|
268
|
+
base, tools, descriptions, prompt_template, allowed_imports, referenceable_tables
|
|
269
|
+
)
|
|
262
270
|
yield SystemInstructionEvent(system_instruction)
|
|
263
271
|
before = serialize(session, base)
|
|
264
272
|
|
|
@@ -268,6 +276,8 @@ def _run(
|
|
|
268
276
|
)
|
|
269
277
|
code = output.code
|
|
270
278
|
|
|
279
|
+
# Note: agent can inline cite tables, we should verify that they are valid (issue 30)
|
|
280
|
+
|
|
271
281
|
# Loop until model is over with the task
|
|
272
282
|
loops = 0
|
|
273
283
|
while code:
|
|
@@ -51,6 +51,29 @@ def _render_imports(allowed_imports: list[str]) -> str:
|
|
|
51
51
|
return f"Only these modules may be imported: {modules}."
|
|
52
52
|
|
|
53
53
|
|
|
54
|
+
def _render_references(base: type[DeclarativeBase], referenceable_tables: list[str] | None) -> str:
|
|
55
|
+
"""Render the row-reference instruction for the allowed tables.
|
|
56
|
+
|
|
57
|
+
Table names are validated against the schema so a typo raises instead of
|
|
58
|
+
silently letting the agent cite a table that does not exist.
|
|
59
|
+
"""
|
|
60
|
+
if not referenceable_tables:
|
|
61
|
+
return ""
|
|
62
|
+
known = base.metadata.tables
|
|
63
|
+
unknown = [name for name in referenceable_tables if name not in known]
|
|
64
|
+
if unknown:
|
|
65
|
+
raise ValueError(
|
|
66
|
+
f"Unknown referenceable table(s): {', '.join(unknown)}. "
|
|
67
|
+
f"Available tables: {', '.join(sorted(known))}."
|
|
68
|
+
)
|
|
69
|
+
names = ", ".join(f"`{name}`" for name in referenceable_tables)
|
|
70
|
+
return (
|
|
71
|
+
f"You can reference specific rows in {names} by inlining "
|
|
72
|
+
f"`[{referenceable_tables[0]}:row_pk]` in your message to the user, "
|
|
73
|
+
"where `row_pk` is the row's primary key value."
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
|
|
54
77
|
def _check_markers(source: str) -> None:
|
|
55
78
|
"""Warn for each required Jinja variable missing from the raw template source."""
|
|
56
79
|
for marker in _REQUIRED_MARKERS:
|
|
@@ -69,6 +92,7 @@ def render(
|
|
|
69
92
|
descriptions: dict[str, str],
|
|
70
93
|
template: str | Path | None = None,
|
|
71
94
|
allowed_imports: list[str] | None = None,
|
|
95
|
+
referenceable_tables: list[str] | None = None,
|
|
72
96
|
) -> str:
|
|
73
97
|
"""Build the system instruction for the LM with all context parts.
|
|
74
98
|
|
|
@@ -81,19 +105,14 @@ def render(
|
|
|
81
105
|
file, or ``None`` to use the shipped default.
|
|
82
106
|
allowed_imports: Modules the agent may import. ``None`` or an empty
|
|
83
107
|
list means imports are forbidden.
|
|
108
|
+
referenceable_tables: Schema table names the agent may cite inline,
|
|
109
|
+
e.g. ``[authors:1]``. ``None`` means citations are disabled.
|
|
84
110
|
"""
|
|
85
111
|
if template is None:
|
|
86
112
|
path: Path = _TEMPLATE_PATH
|
|
87
113
|
source = path.read_text()
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
template=source,
|
|
91
|
-
SCHEMA=_render_schema_source(base=base),
|
|
92
|
-
SYMBOLS=_render_symbols(descriptions),
|
|
93
|
-
TOOLS=_render_tools_summary(tools),
|
|
94
|
-
IMPORTS=_render_imports(allowed_imports or []),
|
|
95
|
-
)
|
|
96
|
-
source = template.read_text() if isinstance(template, Path) else template
|
|
114
|
+
else:
|
|
115
|
+
source = template.read_text() if isinstance(template, Path) else template
|
|
97
116
|
_check_markers(source)
|
|
98
117
|
return render_template(
|
|
99
118
|
template=source,
|
|
@@ -101,4 +120,5 @@ def render(
|
|
|
101
120
|
SYMBOLS=_render_symbols(descriptions),
|
|
102
121
|
TOOLS=_render_tools_summary(tools),
|
|
103
122
|
IMPORTS=_render_imports(allowed_imports or []),
|
|
123
|
+
REFERENCES=_render_references(base, referenceable_tables),
|
|
104
124
|
)
|
|
@@ -4,10 +4,11 @@ You can interact with the database using Python code and SQLAlchemy.
|
|
|
4
4
|
# Guidelines
|
|
5
5
|
- **Code Execution**: Run Python code to query or modify the database. Use `print()` to inspect results.
|
|
6
6
|
- **Imports**: {{ IMPORTS }}
|
|
7
|
-
- **Persistence**: Variables (and any allowed imports) carry over between cells, until the user sends a new message.
|
|
8
7
|
- **Printing**: Keep `print()` statements concise, but print anything you may need in a later turn (ids, key values, short findings).
|
|
9
|
-
- **
|
|
10
|
-
- **
|
|
8
|
+
{% if REFERENCES %}- **References**: {{ REFERENCES }}{% endif %}
|
|
9
|
+
- **Efficiency**: Avoid redundant imports, session initialization and repeated prints.
|
|
10
|
+
- **Iteration**: Use the execution output (sent as an automatic user message) to decide if you need to run more code or provide a final answer to end the turn.
|
|
11
|
+
- **Persistence**: the Python namespace (variables, imports, ...) carry over between cells only within the same turn. A new user message means a newly initialized namespace.
|
|
11
12
|
{% if TOOLS %}- **Tools**: Several tools are available in your namespace. Use `print(disclose(name))` to discover a tool's full signature and docstring before calling it.{% endif %}
|
|
12
13
|
- **Transactions**: the SQLAlchemy `session` is also shared by every cell, nothing is committed or rolled back for you.
|
|
13
14
|
- Uncommitted work piles up across cells.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|