This commit is contained in:
2026-06-04 16:43:55 +00:00
parent 7ad511c2a0
commit 93712268ac
+37 -45
View File
@@ -1,68 +1,64 @@
from langgraph.graph import StateGraph, START, END from langgraph.graph import StateGraph, START, END
from state import ReflectState from state import BriefState
from nodes import generate_answer from nodes import outline_node, research_step_node, synthesize_node
def should_retry(state: ReflectState) -> str: def should_continue_research(state: BriefState) -> str:
""" """
Условие: продолжать попытки или завершить Условие: продолжать исследование или переходить к синтезу
Проверяет наличие ошибки и количество попыток
""" """
# Если ошибки нет - успех if state["step_index"] < len(state["outline"]):
if state["error"] is None: return "continue"
print(f"✅ Ответ успешно сгенерирован за {state['round']} попыт(ок/ки)") else:
return "end" return "synthesize"
# Если есть ошибка и не превышен лимит - повторяем def build_research_graph():
if state["round"] < state["max_rounds"]:
print(f"🔄 Повторная попытка ({state['round'] + 1}/{state['max_rounds']})...")
return "retry"
# Превышен лимит - завершаем с ошибкой
print(f"⚠️ Достигнут лимит попыток ({state['max_rounds']}). Последняя ошибка: {state['error']}")
return "end"
def build_retry_graph(max_rounds: int = 3):
""" """
Строит граф с retry-логикой через try/except Строит граф исследовательского агента
Структура: Структура:
START → generate_answer → should_retry START → outline → research_step → (пока есть пункты) → research_step → synthesize → END
→ (если error None) → END
→ (если error и round < max_rounds) → generate_answer (с увеличенным round)
→ иначе → END
""" """
graph = StateGraph(ReflectState) graph = StateGraph(BriefState)
# Добавляем единственный узел (он же будет вызываться повторно) # Добавляем узлы
graph.add_node("generate_answer", generate_answer) graph.add_node("outline", outline_node)
graph.add_node("research_step", research_step_node)
graph.add_node("synthesize", synthesize_node)
# Добавляем рёбра # Добавляем рёбра
graph.add_edge(START, "generate_answer") graph.add_edge(START, "outline")
graph.add_edge("outline", "research_step")
# Условное ребро после генерации # Условное ребро после research_step
graph.add_conditional_edges( graph.add_conditional_edges(
"generate_answer", "research_step",
should_retry, should_continue_research,
{ {
"retry": "generate_answer", # Петля для повторной попытки "continue": "research_step", # Берём следующий пункт
"end": END "synthesize": "synthesize" # Завершаем исследование
} }
) )
# После синтеза завершаем
graph.add_edge("synthesize", END)
return graph.compile() return graph.compile()
# Пример использования # Пример использования
if __name__ == "__main__": if __name__ == "__main__":
from dotenv import load_dotenv
load_dotenv()
# Создаём граф # Создаём граф
app = build_retry_graph(max_rounds=3) app = build_research_graph()
# Входное состояние # Входное состояние
initial_state = { initial_state = {
"question": "Объясни студенту разницу между tool и resource в MCP", "topic": "Как студенту безопасно подключать MCP к LangChain",
"draft": "", "outline": None,
"error": None, "step_index": 0,
"round": 1, "notes": [],
"max_rounds": 3 "final_brief": None
} }
# Запуск # Запуск
@@ -70,10 +66,6 @@ if __name__ == "__main__":
# Вывод результата # Вывод результата
print("\n" + "="*80) print("\n" + "="*80)
if final_state["error"] is None: print("ИТОГОВЫЙ ИССЛЕДОВАТЕЛЬСКИЙ БРИФ")
print("✅ ФИНАЛЬНЫЙ ОТВЕТ:")
print("="*80) print("="*80)
print(final_state["draft"]) print(final_state["final_brief"])
else:
print("❌ НЕ УДАЛОСЬ СГЕНЕРИРОВАТЬ КАЧЕСТВЕННЫЙ ОТВЕТ")
print(f"Ошибка: {final_state['error']}")