Агентные ИИ с LangChain — Часть 5: Агентный RAG с ReAct и
Часть 5: агентные ИИ с LangChain — агентный RAG, в котором агент ReAct решает, когда запрашивать информацию, а этап рефлексии проверяет ответ перед его возвратом.
Источники: Agentic AI with LangChain — Part 5: Agentic RAG with ReAct and Reflection
Используйте это как переработанную версию идей из статьи «Агентные ИИ с LangChain — Часть 5: Агентный RAG с ReAct и Reflection», ориентированную на операторов: четкие этапы, упорядоченные блоки кода и записи о восстановлении, сохраняющиеся при передаче задач. Обзор работает лучше всего, когда рассматривается как измеримая структура. Соберите один идеальный пример работы, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Предпочитайте небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое какого-либо шага причина должна быть связана с конкретной функцией, а не с запутанной цепочкой операций.
Технические концепции
Что касается технических концепций, необходимо определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия результатам работы, определите критерии успеха и не допускайте молчаливого частичного завершения задачи. Укажите те фрагменты текста, которые легли в основу ответа. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации.
1. Конфигурации системы
1. Для системных конфигураций необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рядом с функциональными результатами следует записывать время выполнения и стоимость токенов или запросов. Отображение стоимости заранее помогает избежать неожиданных счетов при переходе с демо-среды в общедоступные среды. Указывайте те части текста, которые фактически легли в основу ответа. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации.
OPENAI_API_KEY="<Your OpenAI API Key>"
VECTOR_DB=pinecone
PINECONE_API_KEY=<your Pinecone API Key>
PINECONE_ENVIRONMENT=gcp-starter
LANGSMITH_TRACING=true
LANGSMITH_ENDPOINT="https://api.smith.langchain.com"
LANGSMITH_API_KEY="<Your LangSmith API Key"
LANGSMITH_PROJECT="agent-ai"
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/
├── rag_process/ # Pinecone RAG operations
│ ├── __init__.py
│ ├── extractor.py
| └── service.py
│
├── graphs # implement ReAct and Reflection StateGraph
│ ├── nodes.py # graph nodes. Defined as Python functions
│ ├── graph.py # graph workflow
│ ├── consts.py # define node names as constants
│ └── state.py # typed dictionary to store graph states
|
|
├── tools # defines Pinecone retriever and get_weather tools
│ ├── retriever_tools.py # Python function tool to retrieve Pinecone RAG
| └── weather.py # typed dictionary to store graph states
|
|── schemas.py # pydantic data models
|── upload.py # python functions to upload files asynchronously
├── main.py # fastAPI app
├── config.py # pydantic BaseConfig
│── dependencies.py # dependency inject to fastAPI endpoint function
├── .env # environment variable definition
├── client.py # streamlit client
├── .gitignore
└── requirements.txt # package requirements
3. Интеграция шаблона ReAct
Для пункта 3. Интеграция шаблона ReAct необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Необходимо одновременно задокументировать успешный сценарий выполнения и сценарий восстановления. Повторные попытки, проверки человеком и обработка неработоспособных сообщений являются частью продукта, а не последующими улучшениями. Указывайте конкретные фрагменты текста, на которых основан ответ. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации.
3.1. Инструмент поиска RAG
Для инструмента поиска RAG 3.1 необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Лучше использовать небольшие, тестируемые единицы кода вместо обширных скриптов. При сбое шага причина должна быть связана с конкретной функцией, а не с запутанной структурой обработки данных. Указывайте те фрагменты текста, на которых основан ответ. Без цитат операторы не смогут отличить галлюцинации от проблем с индексацией.
@tool
async def search_agentic_docs(query: str) -> str:
"""
Good for questions about generative agents, prompt engineering, and adversarial attacks.
Pass a natural language search query to retrieve context from the agentic ai database.
"""
# Simply invoke your existing vector service retriever
docs = await vector_service.retriever.ainvoke(query)
# Flatten the document content into a single string for the LLM
return "\n\n".join([d.page_content for d in docs])
3.2. GraphState
Для раздела 3.2. GraphState необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Укажите названия элементов, определите критерии успеха и не допускайте молчаливого частичного завершения работы. Цитируйте те фрагменты, которые фактически легли в основу ответа. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации.
class GraphState(TypedDict):
"""
Represents the state of our graphs.
Attributes:
question: question
generation: LLM generation
acceptable: whether the answer is qualified to be acceptable
messages: list of messages
"""
question: str
generation: str
acceptable: bool
messages: Annotated[list[AnyMessage], add_messages]
loop_count: int
3.3. Узлы ReAct
Для модулей ReAct версии 3.3 необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не пытаясь угадать скрытое состояние. Рядом с функциональными результатами следует записывать время выполнения и стоимость токенов или запросов. Отображение стоимости заранее помогает избежать неожиданных счетов при переходе от демо-среды к общедоступным средам. Указывайте конкретные фрагменты текста, на которых основан ответ. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации.
4. Интеграция шаблона рефлексии
Для пункта 4. Интеграция шаблона рефлексии необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, которое операторы могут проверять, не читая весь код. Указывайте те участки текста, которые фактически легли в основу ответа. Без цитат операторы не смогут отличить галлюцинации от пробелов в индексации. Для пункта 4. Интеграция шаблона рефлексии необходимо заранее определить входные данные, ответственного за выполнение шага и критерии завершения перед изменением кода. Операторы должны иметь возможность перезапустить шаг с известной точки контроля, не догадываясь о скрытом состоянии. Предпочитайте небольшие, тестируемые единицы кода большим развернутым скриптам. При сбое шага он должен указывать на конкретную проблему, а не на запутанную структуру кода.
Элине.
4.1. Как работает рефлексия
При изучении раздела 4.1. Как работает рефлексия сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и что происходит при частичной неудаче. Такой список поможет сохранять честность при последующих изменениях кода. Рассматривайте этот этап как договор между входными данными и проверенными выходными результатами. Дайте названия элементам кода, определите критерии успешности и не допускайте молчаливого частичного выполнения задачи. Оцените уровень воспроизводимости на фиксированном наборе вопросов перед настройкой подсказок. Частая смена подсказок редко помогает улучшить качество поиска информации.
4.2. Подсказки
При работе над разделом 4.2. Promptы сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и действия при частичной неудаче. Такой чек-лист поможет избежать ошибок при последующих изменениях кода. Рядом с функциональными результатами записывайте время выполнения и стоимость токенов или запросов. Отслеживание затрат с самого начала предотвращает неожиданные расходы при переходе с демо-среды в общедоступные среды. Храните в кэше стабильные инструкции системы и схемы инструментов. Повторная отправка одинаковых данных — частая причина избыточных затрат.
GENERATE_SYSTEM_PROMPT = f"""You are an assistant for question-answering tasks with access to multiple tools.
use these tools to retrieve context to answer the question. If you don't know the answer,
just say that you don't know. Use three sentences maximum and keep the answer concise.
Tool Use Instructions:
- Use tools as much as possible.
- Chain tools when needed (e.g., search for info, then use that to search
for relevant hotels)
- Be conversational and helpful
- If you choose to answer a question using your internal knowledge instead of a tool,
you must be completely certain of the facts. If there is any ambiguity,
or if the question requires up-to-date or highly specific details, you MUST use a tool to verify.
"""
GRADER_SYSTEM_PROMPT = """""You are a grader assessing whether an LLM generation addresses/resolves a
question using the context. Generate critique and recommendations for LLM that generated the answer.
always provide detailed recommendations, including requests for search more relevant context, generate
answer based on context to reduce hallucination, and generate answer relevant to the question.
The LLM generating this answer has the access to the following tools to obtain context:
**get_weather**: search for weather information given a city name
**search_agentic_docs**: Good for questions about generative agents, prompt engineering, and adversarial attacks
**TavilySearch**: General search tool from the internet.
INSTRUCTIONS:
(a) Evaluate if the context is relevant to the question
Provide recommendation if context is not relevant to the question. You can suggest the LLM to use an
appropriate tool. If there is no context, you must be completely certain of the facts. If the question is
covered by provided tools, or there is any ambiguity,
or if the question requires up-to-date or highly specific details, you MUST suggest to use a tool to verify answer.
(b) Evaluate if the answer is based on the context
if the answer is not based on the context, it is a hallucination. You should suggest to regenerate the answer
based on the context.
(c) Evaluate if the answer resolves the question
if the answer does not resolves the question, suggest to regenerate the answer
The LLM generated this answer is strictly instructed to keep its answer CONCISE (maximum of 3 sentences).
Do NOT penalize the answer for omitting minor details if the core question is answered accurately.
If all the evaluations are passed, no suggestions should be provided.
CRITERIA FOR ACCEPTABLE (True):
- If the answer is accurate, addresses the user's question using the context, and does not hallucinate,
you MUST set acceptable to True, even if it missed some details from the context.
- Only set acceptable to False if there is a fundamental flaw (hallucination, wrong information,
or completely missing the point).
OUTPUT REQUIREMENTS:
You must return a structured output with the following fields:
- acceptable (boolean): True if the answer passed all evaluation,
False if any of the evaluation fails and recommendations are provided
- recommendations (string): recommendations you provide
INPUTS:
question: {question}
answer: {answer}
context: {context}
"""
4.3. Узлы отражения
При работе над разделом 4.3. Узлы отражения сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и что происходит при частичной неудаче. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Храните конфигурацию вне кода приложения. Файлы среды, хранилища секретов и флаги функций должны находиться в одном месте, чтобы операторы могли их проверять, не читая весь код. Измеряйте точность воспроизведения ответов на фиксированном наборе вопросов перед настройкой подсказок. Частая смена подсказок редко помогает улучшить качество поиска. При работе над разделом 4.3. Узлы отражения сначала запишите условия работы: необходимые входные данные, сигнал о успешном выполнении и что происходит при частичной неудаче. Такой чек-лист поможет сохранять честность при последующих изменениях кода. Предпочитайте небольшие, тестируемые единицы кода большим скриптам. Когда какой-то шаг не срабатывает, причина должна быть связана с одной конкретной функцией, а не с запутанной цепочкой операций.
5. Полный рабочий процесс
- Полный рабочий процесс наилучшим образом функционирует, когда его рассматривают как измеримую структуру. Соберите один идеальный пример выполнения, один случай сбоя и запись о возврате к предыдущему состоянию перед расширением объема работ. Рассматривайте этот этап как контракт между входными данными и проверенными результатами. Дайте названия создаваемым документам, определите критерии успеха и не соглашайтесь на молчаливое частичное выполнение задачи. Разделяйте политику разбиения работы на части и политику извлечения данных. Изменение одной из них не должно приводить к переписыванию другой при изменении показателей качества.