add
This commit is contained in:
@@ -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["final_brief"])
|
||||||
print(final_state["draft"])
|
|
||||||
else:
|
|
||||||
print("❌ НЕ УДАЛОСЬ СГЕНЕРИРОВАТЬ КАЧЕСТВЕННЫЙ ОТВЕТ")
|
|
||||||
print(f"Ошибка: {final_state['error']}")
|
|
||||||
Reference in New Issue
Block a user