Практические заметки: Агентные ИИ с LangChain — Часть 3: Вызов инструментов в LangChain
Пошаговое руководство по практическим заметкам: агентные ИИ с LangChain — Часть 3: вызов инструментов в LangChain: контракты, проверки и готовые блоки кода для команд, использующих эту модель.
Используйте это как переработанную версию идей из статьи «Агентные ИИ с LangChain — Часть 3: Вызов инструментов в LangChain», ориентированную на операторов: четкие этапы, упорядоченные блоки кода и записи о восстановлении, которые сохраняются при передаче задач. Этап Обзора работает наилучшим образом, если рассматривать его как измеримую основу. Соберите один идеальный пример работы, один случай сбоя и записи о возврате к предыдущему состоянию перед расширением объема работ. Записывайте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отображение стоимости заранее предотвращает неожиданные счета при переходе от демо-версии к общим средам.
Концепции вызова инструментов
На этапе концепций вызова инструментов необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь кодовый граф. Аутентификация происходит на шлюзе, а повторная авторизация — на уровне обработки данных. Один только токен-носитель не является границей между тенантами.
1. Конфигурации системы
На этапе 1 «Конфигурация системы» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо задокументировать как успешный, так и восстановительный сценарии работы. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Аутентификация происходит на шлюзе, а повторная авторизация — на уровне данных. Один только токен-носитель не является границей между тенантами.
OPENAI_API_KEY="<Your OpenAI API Key>"
TAVILY_API_KEY=<Your TAVILY API Key>
class BaseConfig(BaseSettings):
OPENAI_API_KEY: Optional[str]
PINECONE_API_KEY: Optional[str]
TAVILY_API_KEY: Optional[str]
model_config = SettingsConfigDict(env_file=".env", extra="ignore")
2. Структура проекта
На этапе 2 «Структура проекта» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага он должен указывать на конкретную причину, а не на сложную взаимосвязь всех этапов. Аутентификация происходит на входе, а повторная авторизация — на уровне обработки данных. Одного только токена не достаточно для определения границ аренды.
project/
|
├── tools
│ ├── get_sum.py # a simple LangChain tool example
| └── weather.py # get_weather LangChain tool using open source APIs
|
|── tool_call.py # implement tool-calling loop using LangChain tools
├── config.py # pydantic BaseConfig
├── .env # environment variable definition
├── .gitignore
└── requirements.txt # package requirements
3. Инструменты LangChain
На этапе 3 инструментов LangChain необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Укажите названия результатов работы, определите критерии успеха и не допускайте молчаливого частичного завершения задачи. Аутентифицируйтесь у шлюза и повторно авторизуйтесь на уровне обработки данных. Одного только токена-носителя недостаточно для обозначения границы тенантности.
3.1. Что такое инструмент LangChain?
На этапе 3.1 «Что это?» необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг, исходя из известной точки контроля, без необходимости угадывания скрытого состояния. Рядом с функциональными результатами следует записывать время выполнения и стоимость токена или запроса. Отображение стоимости заранее предотвращает неожиданные счета при переходе с демо-среды в общедоступные среды. Аутентификация происходит на шлюзе, а повторная авторизация — на уровне данных. Один только токен-носитель не является границей между тенантами.
from langchain.tools import tool
@tool
def get_sum(a: int, b: int) -> int:
"""
get the summation of two integers
:param a: int, input integer
:param b: int, input integer
:return: int, the sum of a and b
"""
return a + b
3.2. Реализация инструмента прогноза погоды
Для раздела 3.2 необходимо сначала реализовать соответствующую стадию, определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Конфигурацию следует хранить отдельно от кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь кодовый граф. Аутентификация происходит на шлюзе, а повторная авторизация — на уровне обработки данных. Один только токен-носитель не является границей между тенантами.
3.3. Концепция вызова инструментов
Для концепции этапа 3×3 необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо одновременно задокументировать успешный сценарий выполнения и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не этапом последующей доработки. Аутентификация происходит на шлюзе, а повторная авторизация — на уровне данных. Один только токен-носитель не является границей между тенантами.
3.4. Вызов инструментов в LangChain
На этапе вызова инструментов 3 4 необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной структурой обработки данных. Аутентификация происходит на входе, а повторная авторизация — на уровне обработки данных. Одного только токена недостаточно для определения границ использования ресурсов. На этапе вызова инструментов 3 4 необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед внесением изменений в код. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рядом с функциональными результатами следует записывать время выполнения, стоимость токенов или запросов. Отслеживание затрат на раннем этапе предотвращает неожиданные счета при переходе от демо-среды к общедоступным средам.
3.4.1. Настройка LLM и инструментов
Во время этапа настройки 3 4 1 сначала запишите условия работы: необходимые входные данные, сигнал успешного выполнения и действия при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Храните в кэше стабильные инструкции системы и схемы инструментов. Повторная отправка одинаковых данных — распространенная причина ресурсозатрат.
class WeatherAssistant:
def __init__(self):
# initialize llm
self.llm = ChatOpenAI(api_key=api_key, model="gpt-4o-mini", temperature=0)
# initialize a tool dictionary
self.tools = {"get_weather": get_weather,
"tavily_search": TavilySearch(max_results=3, tavily_api_key=TAVILY_API_KEY)}
# bind LangChain tools to llm
self.llm_with_tools = self.llm.bind_tools(list(self.tools.values()))
# initialize messages to store message list
self.messages = []
# System prompt
self.system_prompt = f"""You are a helpful assistant for question-answering tasks.
When users ask about weather, use the get_weather tool to get weather. For other questions,
use web_search. If you don't know the answer, just say that you don't know.
Be conversational and helpful in your responses."""
self.messages.append(SystemMessage(content=self.system_prompt))
3.4.2. Реализация цикла вызова инструментов
При работе над этапом реализации 3 4 2 сначала запишите контракт: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист помогает сохранять честность при последующих изменениях кода. Задокументируйте одновременно успешный сценарий работы и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не элементами последующей доработки. Фиксируйте имя инструмента, хеш аргументов, время задержки и результат каждого вызова. Без такой записи отладка агента, работающего в цикле, тратит много времени.
async def chat(self, message: str):
# Wrap User message in a HumanMessage and add it to message list
self.messages.append(HumanMessage(content=message))
# Get AI response (it may or may not contain tool calls)
response = await self.llm_with_tools.ainvoke(self.messages)
self.messages.append(response)
# If there is any tool calls in the AI response
if response.tool_calls:
# process tool calls
for tool_call in response.tool_calls:
# retrieve function name from tool_call, then
# retrieve the tool from tool dictionary, and invoke it,
# append resulting tool message to message list
tool = self.tools[tool_call["name"]]
tool_result = await tool.ainvoke(tool_call)
self.messages.append(tool_result)
# Get final response after tool execution
final_response = await self.llm_with_tools.ainvoke(self.messages)
self.messages.append(final_response)
3.4.3 Тестирование цикла
Во время этапа тестирования 3 4 3 сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист поможет сохранять честность последующих изменений в коде. Предпочитайте небольшие, тестируемые единицы кода большим скриптам. Когда какой-то шаг не срабатывает, причина должна быть связана с одной конкретной функцией, а не с запутанной цепочкой операций. Записывайте название инструмента, хеш аргументов, время задержки и результат каждого вызова. Без этих данных отладка занимает много времени. Во время этапа тестирования 3 4 3 сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист поможет сохранять честность последующих изменений в коде. Регистрируйте время выполнения и стоимость токенов или запросов рядом с функциональными результатами. Отслеживание затрат с самого начала предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды.
async def main():
print("hello tool calling!")
assistant = WeatherAssistant()
message = "What is the temperature in Tokyo?"
await assistant.chat(message)
for msg in assistant.messages:
msg.pretty_print()
if __name__ == "__main__":
asyncio.run(main())
4. Ограничения базового цикла вызова инструментов
Четыре ограничения данного подхода наилучшим образом проявляют себя при рассмотрении его как измеримой структуры. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Обеспечьте доступ к инструментам с узкими схемами и четкими метками о побочных эффектах. Хостам необходимо знать, какие вызовы изменяют состояние, прежде чем они автоматически одобрят их.
5. Заключение
Этап «5. Заключительный обзор» работает наилучшим образом, если рассматривать его как измеримую основу. Соберите один идеальный пример работы, один случай сбоя и записку о возврате к предыдущему состоянию перед расширением объема работ. Документируйте одновременно успешный и восстановительный сценарии. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не этапом последующей доработки. Используйте инструменты с узкими схемами и четкими метками побочных эффектов. Администраторам необходимо знать, какие вызовы изменяют состояние, прежде чем они автоматически одобрят операцию.
Чек-лист операционной работы
При работе над этапом чек-листа операционной работы сначала опишите контракт: необходимые входные данные, сигнал успеха и действия при частичном сбое. Этот чек-лист помогает сохранять честность при последующих изменениях кода. Рассматривайте этот этап как контракт между входными данными и проверенными выходными результатами. Дайте названия элементам, определите критерии успеха и не допускайте безответственного частичного выполнения задач.
Записывайте название инструмента логгинга, хеш аргументов, время задержки и результат каждого вызова. Отладка без такой информации тратит часы впустую.
Сохраняйте структуру графа простой и типизированной. Вложенные структуры данных мешают понять, какой узел заполнил тот или иной поле, и нарушают возможность продолжения работы после прерываний.
При наличии бюджета добавляйте тесты на работоспособность критического пути в процессе интеграционного тестирования с использованием фикстур, а не реальных платных API.
Документируйте как успешный, так и восстановительный пути работы. Повторные попытки, проверки человеком и обработка неработающих сообщений являются частью продукта, а не дополнительными улучшениями.
Перед внедрением новой стековой технологии заморозьте версии, сохраните эталонный отчет для критического пути и уточните шаги отката. В совместных средах необходимы ограничения на частоту запросов, проверки принадлежности и четко определенный ответственный за обновление секретов. Лучше надежность без изысков, чем красивые одноразовые демонстрации.
Примечание к пакету d7ca1ebeb899: не храните ключи поставщиков в репозитории, установите лимит токенов на сессию и сохраняйте транскрипции рядом с фиксами для оценки, чтобы последующие замены моделей оставались сопоставимыми.