Практические советы: Агент текста-в-SQL в Python: руководство по вызову инструментов LLM
Пошаговое руководство по практическим заметкам: агент Text-to-SQL в Python: учебник по использованию инструментов больших языков моделей: контракты, проверки и готовые блоки кода для команд, применяющих эту схему.
В этом руководстве пошагово описывается путь от сырья до готовой к работе системы для создания агента Text-to-SQL на Python, где единственным кодом является сам инструмент. Основное внимание уделяется практическим шагам, четкой проверке результатов и коду, который можно просто добавить в репозиторий без необходимости догадываться о его назначении. Для обзора необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии системы. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия создаваемым элементам, определите критерии успеха и не допускайте безответственного частичного выполнения задачи.
Разделение: определение и реализация
При работе над материалом «Разделение: определение против реализации» сначала запишите условия интерфейса: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Рядом с функциональными результатами записывайте время выполнения, стоимость токенов или запросов. Очевидность затрат с самого начала предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды. Ведите журнал с информацией об идентификаторе запроса, идентификаторе модели и времени задержки при каждом вызове. Без такой отчетности периодические ошибки поставщика могут выглядеть как баги приложения.
Что вам понадобится
При работе над разделом «Что вам нужно», сначала запишите условия контракта: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Храните конфигурацию отдельно от кода приложения. Файлы с настройками окружения, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код приложения. Записывайте идентификатор запроса, идентификатор модели и время задержки при каждом вызове. Без такой отчетности периодические ошибки поставщика будут выглядеть как баги в самом приложении.
pip install acruxcore
1. Заполните базу данных данными, подлежащими поиску
При работе над пунктом 1 «Заполнение базы данных, годной для запросов», сначала запишите условия взаимодействия: необходимые параметры, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Документируйте как успешный, так и восстановительный сценарии работы. Повторные попытки, проверки со стороны человека и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Ведите журнал записей с идентификатором запроса, идентификатором модели и временем задержки при каждом вызове. Без такой отчетности периодические ошибки поставщика будут выглядеть как баги приложения. При работе над пунктом 1 «Заполнение базы данных, годной для запросов», сначала запишите условия взаимодействия: необходимые параметры, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Рассматривайте этот этап как договор между входными данными и проверенными результатами. Дайте названия соответствующим элементам, определите критерии успеха и не допускайте безусловного частичного выполнения задач.
conn.executescript("""
CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, category TEXT, price REAL, stock INTEGER);
CREATE TABLE orders (id INTEGER PRIMARY KEY, product_id INTEGER REFERENCES products(id),
quantity INTEGER, order_date TEXT, customer TEXT);
""")
conn.executemany("INSERT INTO products VALUES (?, ?, ?, ?, ?)", PRODUCTS)
conn.executemany("INSERT INTO orders VALUES (?, ?, ?, ?, ?)", ORDERS)
python seed_db.py
# Seeded store.db: 8 products, 15 orders.
2. Регистрация модели в панели управления
- Регистрация модели в панели управления будет наиболее эффективной, если рассматривать её как измеримую поверхность. Сначала соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию, прежде чем расширять объём работ. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости на раннем этапе помогает избежать неожиданных счётов при переходе от демо-среды к общедоступным средам. Перед настройкой циклов закрепите интерпретатор и файл с информацией о зависимостях. Различия в работе между ноутбуком и средой CI являются наиболее частой причиной скрытых сбоев в демо-версиях API.
3. Заполнение промпта в панели управления
- Наилучший способ использования панели управления для написания запросов — рассматривать её как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Храните конфигурацию вне кода приложения: файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Заблокируйте интерпретатор и файлы с информацией о зависимостях перед тем, как использовать циклы; различия между ноутбуком и средой CI являются наиболее распространённой причиной скрытых сбоев в демонстрациях API.
You are a data analyst for an online store. Answer questions about products and
sales by querying a SQLite database with the query_database tool. Never guess —
always query.
Schema:
CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, category TEXT, price REAL, stock INTEGER);
CREATE TABLE orders (id INTEGER PRIMARY KEY, product_id INTEGER REFERENCES products(id), quantity INTEGER, order_date TEXT, customer TEXT);Write a single read-only SQLite SELECT, call query_database with it, then answer
in one or two sentences using only the rows it returns. Prices are in USD;
revenue = quantity * price; order_date is YYYY-MM-DD.
4. Определите инструмент в коде — и позвольте ему самостоятельно публиковаться
- Определение инструмента в коде — и возможность его самостоятельной публикации — работают наилучшим образом, когда их рассматривают как измеримые показатели. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Документируйте как успешный, так и восстановительный сценарии работы. Повторные попытки, проверки со стороны человека и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Фиксируйте версию интерпретатора и файлы блокировки зависимостей до того, как начнёте использовать циклы. Различия между лаптопом и средой CI являются наиболее распространённой причиной скрытых сбоев в демонстрациях API.
- Определение инструмента в коде — и возможность его самостоятельной публикации — работают наилучшим образом, когда их рассматривают как измеримые показатели. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объёма работ. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия всем элементам, определите критерии успеха и не допускайте скрытого частичного завершения работы.
from acruxcore import AcruxCore, acrux
@acrux.tool
async def query_database(sql: str) -> list[dict]:
"""Run a read-only SQL SELECT against the store database. Args:
sql: A single read-only SQLite SELECT statement.
"""
statement = sql.strip().rstrip(";").strip()
if not statement.lower().startswith("select"):
raise ValueError("Only read-only SELECT statements are allowed.")
if ";" in statement:
raise ValueError("Only a single statement is allowed.")
conn = sqlite3.connect(f"file:{DB_PATH}?mode=ro", uri=True)
conn.row_factory = sqlite3.Row
try:
return [dict(row) for row in conn.execute(statement).fetchall()]
finally:
conn.close()
{
"name": "query_database",
"description": "Run a read-only SQL SELECT against the store database.",
"parameters": {
"type": "object",
"properties": {
"sql": {"type": "string", "description": "A single read-only SQLite SELECT statement."}
},
"required": ["sql"]
}
}
async with AcruxCore() as hub:
await hub.tools.sync([query_database])
5. Пусть панель управления определяет формулировки инструмента
Для пункта 5 «Пусть панель управления определяет формулировки инструмента» необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рядом с функциональными результатами следует записывать время выполнения, а также стоимость токенов или запросов. Отображение стоимости заранее помогает избежать неожиданных счетов при переходе с демо-среды в общедоступные среды. Необходимо разделить процесс создания клиента от цикла обработки сообщений, чтобы можно было заменять поставщиков без переписывания машины состояний диалога.
@acrux.tool
async def check_disclosure_policy(field: str) -> dict:
# No docstring, on purpose. See below — the absence is the mechanism.
sensitive = field.strip().lower() in {"customer", "customer_name", "email"}
return {
"field": field,
"may_disclose": not sensitive,
"guidance": (
"Do not name an individual customer. Report aggregate figures only."
if sensitive
else "This column may be shown to the user."
),
}
{
"name": "check_disclosure_policy",
"description": null,
"parameters": {
"type": "object",
"properties": {"field": {"type": "string"}},
"required": ["field"]
}
}
Published: ToolSyncResult(tool_id='2572965e-…', version_number=2, committed=False, alias='production', superseded_source=None)
6. Запустить его
Для пункта 6: перед изменением кода запустите процесс, определите входные данные, ответственного за шаг и критерии завершения. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Храните конфигурацию вне кода приложения — файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, которое операторы могут проверять, не читая весь граф процессов. Разделяйте создание клиента и цикл обработки сообщений, чтобы можно было заменять поставщиков без переписывания машины состояний диалога.
async def ask(hub: AcruxCore, question: str) -> str:
rendered = await hub.prompts.render("sql-analyst-agent", "production")
messages = [*rendered.messages, {"role": "user", "content": question}]
result = await hub.gateway.run_prompt_with_tools(
rendered,
messages=messages,
tools=[query_database, check_disclosure_policy],
trace={"name": "sql-analyst-agent", "session_id": "sql-agent-demo"},
)
print(f" (trace {result.trace_id})")
return result.content
export ACRUXCORE_API_KEY=<your personal api key>
export ACRUXCORE_BASE_URL=https://api.acruxcore.com/api/v1
python sql_agent.py
Q: Which product generated the most total revenue, and how much?
(trace 606dbd38-cb34-4cc3-a1a1-ec4dc9af87b2)
A: The **Aeron Chair** generated the most total revenue at **$4,185.00**.
Q: How many total units were ordered in June 2026?
(trace d1ace20b-ae00-4c4d-9294-a613327e1583)
A: In June 2026, a total of **93 units** were ordered.Q: Who is our biggest customer by total spend?
(trace ea57a392-9af2-41b6-bfd8-48297ee17a8c)
A: Our biggest customer by total spend has spent $6,995.00. I'm unable to disclose the
specific customer name due to privacy policy, but I can confirm this is our top
customer by total spending.
7. Чтение трейса
Для пункта 7: прочитайте трейс, определите входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Документируйте как успешный путь выполнения, так и путь восстановления. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не последующими улучшениями. Разделите создание клиента от цикла обработки сообщений, чтобы можно было заменять поставщиков без переписывания машины состояний обмена сообщениями. Для пункта 7: прочитайте трейс, определите входные данные, ответственного за шаг и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными выходными данными. Дайте названия результатам работы, определите критерии успеха и не допускайте безответных частичных завершений.
8. Группировка запусков в сессию
При работе над группой 8, сталкиваясь с сессией, сначала запишите условия использования: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Рядом с функциональными результатами записывайте время выполнения, стоимость токенов или запросов. Отслеживание затрат с самого начала предотвращает неожиданные счета при переходе с демо-среды в общедоступные среды. Ведите журнал с информацией об идентификаторе запроса, идентификаторе модели и времени задержки при каждом вызове. Без такой записи периодические ошибки поставщика могут выглядеть как баги приложения.
9. Преимущества: изменение модели без правки кода
При работе над разделом 9 «Выгода: изменение модели без правки кода» сначала запишите спецификацию: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Храните конфигурацию вне кода приложения — файлы с настройками окружения, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код.
Должен ли ваш код вообще управлять инструментом?
При решении вопроса «Должен ли ваш код владеть инструментом?» сначала запишите контракт: необходимые входные данные, сигнал о успехе и то, что происходит при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Документируйте одновременно успешный сценарий и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не последующими улучшениями. Записывайте идентификатор запроса, идентификатор модели и время задержки при каждом вызове. Без такой записи периодические ошибки поставщика кажутся багами приложения. При решении вопроса «Должен ли ваш код владеть инструментом?» сначала запишите контракт: необходимые входные данные, сигнал о успехе и то, что происходит при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными данными. Дайте названия результатам работы, определите критерии успеха и не допускайте безусловного частичного выполнения задачи.
Как двигаться дальше
Определение следующего шага наиболее эффективно при рассмотрении его как измеримой величины. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ.
Чек-лист операционной деятельности
Чек-лист операционной деятельности наиболее эффективен при рассмотрении его как измеримой величины. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ.
Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое какого-либо шага причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций.
Заблокируйте версии интерпретатора и файлы блокировки зависимостей перед демонстрацией цикла. Различия между ноутбуком и средой CI являются наиболее частой причиной незаметных сбоев в демонстрациях API.
Аутентифицируйтесь в шлюзе и повторно авторизуйтесь на уровне обработки данных. Один только токен-носитель не является границей между тенантами.
Создавайте контрольные точки после дорогостоящих операций. Система возобновления работы не должна снова взимать плату за один и тот же вызов большой языковой модели при повторной попытке обработки последующего этапа.
Заблокируйте версии зависимостей и запишите хэш изображения, с использованием которого выполнялась демонстрация. Воспроизводимость важнее устного опыта сотрудников.
Перед масштабированием стека заморозьте версии, сохраните эталонный отчет для критической части работы и убедитесь в наличии шагов для отката. В совместных средах необходимы ограничения по частоте запросов, проверки тенантов и четко определенный ответственный за обновление секретов. Лучше надежность, чем креативные одноразовые демонстрации.
Примечание к пакету a664c3276a43: не включайте ключи поставщиков в репозиторий, установите лимит токенов на сессию и храните транскрипции рядом с фиксами для оценки, чтобы последующие замены моделей оставались сопоставимыми.
При работе над примечанием по усилению безопасности №0 сначала запишите контракт: необходимые входные данные, сигнал успешного выполнения и последствия частичной неудачи. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Предпочитайте небольшие, проверяемые единицы кода вместо обширных скриптов. Если какой-то шаг проваливается, причина неудачи должна указывать на конкретную ответственность, а не на запутанную цепочку операций.
Деталь усиления безопасности 0/766: измерьте время выполнения, класс ошибки и расход токенов для этого примечания, затем решите, следует ли сохранять изменение на основе фиксированного набора критериев, а не на основе устных замечаний.
Примечание по укреплению 1 наилучшим образом работает, если рассматривать его как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
Подробность укрепления 1/766: измерьте время выполнения, класс ошибки и расход токенов для этого примечания, затем решите, следует ли сохранять изменения, опираясь на фиксированный набор вопросов, а не на устные описания.
Для примечания по укреплению 2 определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Документируйте как успешный путь выполнения, так и путь восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не элементами последующей доработки.
Подробности усиления безопасности 2/766: измерьте время выполнения, класс ошибки и расход токенов для этой записи, затем решите, следует ли сохранить изменение на основе фиксированного набора вопросов, а не на основе единичных примеров.
При работе над записью об усилении безопасности №3 сначала запишите контракт: необходимые входные данные, сигнал успешного выполнения и что происходит при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными данными. Дайте названия элементам, определите критерии успеха и не допускайте безответственного частичного выполнения задач.
Подробности усиления безопасности 3/766: измерьте время выполнения, класс ошибки и расход токенов для этой записи, затем решите, следует ли сохранить изменение на основе фиксированного набора вопросов, а не на основе единичных примеров.
Рекомендация по усилению безопасности №4 наиболее эффективна, когда рассматривается как измеримая поверхность. Соберите один образец успешной работы, один пример сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Храните конфигурацию вне кода приложения: файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код.
Подробность усиления безопасности 4/766: измеряйте время выполнения, класс ошибки и расход токенов для этой рекомендации, затем принимайте решение о сохранении изменений на основе определенного набора критериев, а не на основе устных описаний.
Для рекомендации по усилению безопасности №5 определите входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность повторно выполнить шаг, исходя из известной точки контроля, без необходимости угадывать скрытое состояние. Предпочитайте небольшие, проверяемые единицы кода вместо обширных скриптов; при сбое шага причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций.
Подробности усиления безопасности 5/766: измерьте время выполнения, класс ошибки и расход токенов для этой записи, затем решите, следует ли сохранить изменения на основе фиксированного набора вопросов, а не на основе единичных примеров.
При работе над записью об усилении безопасности 6 сначала запишите контракт: необходимые входные данные, сигнал успешного выполнения и что происходит при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Записывайте временные показатели и стоимость токенов или запросов рядом с функциональными результатами. Очевидность затрат заранее предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды.
Подробности усиления безопасности 6/766: измерьте время выполнения, класс ошибки и расход токенов для этой записи, затем решите, следует ли сохранить изменения на основе фиксированного набора вопросов, а не на основе единичных примеров.
Примечание по укреплению безопасности №7 наилучшим образом работает, когда его рассматривают как измеримую поверхность. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объёма работ. Документируйте одновременно успешный сценарий работы и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не последующими доработками.
Подробности укрепления безопасности №7/766: измеряйте время выполнения операций, класс ошибок и расход токенов для этого примечания, затем решайте о сохранении изменений на основе фиксированного набора вопросов, а не на основе единичных примеров.