feat: solution for unknown

This commit is contained in:
+65 -47
View File
@@ -1,57 +1,75 @@
from langchain_openai import ChatOpenAI from langchain_openai import ChatOpenAI
from pydantic import SecretStr from pydantic import SecretStr
from langgraph.graph import StateGraph, START, END, interrupt import argparse
from langgraph.checkpoint.memory import InMemorySaver import sys
from typing import TypedDict
# LLM placeholder def parse_args() -> argparse.Namespace:
llm = ChatOpenAI( """
model="openai/gpt-oss-20b", Parse command line arguments.
base_url='https://platform.brojs.ru/jrnl-bh/api/inference/v1',
api_key=SecretStr("jrnl_30283ab953615cbb6846ff9940a1eedce0b76d7b2f59a2394f29e74643e6a90d"),
temperature=0.7,
)
# State definition Returns:
class GraphState(TypedDict): Namespace: Parsed arguments containing the task text.
human_value: str | None """
parser = argparse.ArgumentParser(
description="Run an LLM-based task orchestrator."
)
parser.add_argument(
"--task-text",
required=True,
help="Text of the task to be processed by the LLM.",
)
return parser.parse_args()
# Node that triggers an interrupt with a question and options def validate_task_text(text: str) -> None:
def ask_node(state: GraphState) -> dict: """
return interrupt( Validate that the provided task text is non-empty.
{
"type": "question", Raises:
"question": "Выберите вариант:", ValueError: If the text is empty or consists only of whitespace.
"options": ["Опция 1", "Опция 2", "Опция 3"], """
} if not text.strip():
raise ValueError("Task text must be a non-empty string.")
def init_llm() -> ChatOpenAI:
"""
Initialize the LLM client with placeholder configuration.
Returns:
ChatOpenAI: Configured LLM instance.
"""
return ChatOpenAI(
model="openai/gpt-oss-20b",
base_url='https://platform.brojs.ru/jrnl-bh/api/inference/v1',
api_key=SecretStr("jrnl_30283ab953615cbb6846ff9940a1eedce0b76d7b2f59a2394f29e74643e6a90d"),
temperature=0.7,
) )
# Build the graph def main() -> None:
builder = StateGraph(GraphState) """
builder.add_node("ask", ask_node) Main entry point of the orchestrator.
builder.set_entry_point(START) Parses arguments, validates input, initializes LLM, and prints the response.
builder.add_edge(START, "ask") """
builder.add_edge("ask", END) args = parse_args()
try:
validate_task_text(args.task_text)
except ValueError as exc:
print(f"Error: {exc}", file=sys.stderr)
sys.exit(1)
graph = builder.compile(checkpointer=InMemorySaver()) llm = init_llm()
# Invoke the LLM with the task text
# Main loop handling interrupts response = llm.invoke(
state: GraphState = {"human_value": None} {"messages": [{"role": "human", "content": args.task_text}]}
while True: )
result = graph.invoke(state) # The result contains a list of messages; we print the content of the first AI message.
if "__interrupt__" in result: ai_message = next(
interrupt_data = result["__interrupt__"] (msg for msg in response["messages"] if getattr(msg, "type", None) == "ai"),
print(interrupt_data["question"]) None,
for idx, opt in enumerate(interrupt_data["options"], 1): )
print(f"{idx}. {opt}") if ai_message:
choice = input("Выберите номер: ").strip() print(ai_message.content)
try:
selected = interrupt_data["options"][int(choice) - 1]
state["human_value"] = selected
except (ValueError, IndexError):
print("Неверный выбор. Повторите.")
else: else:
break print("No AI response received.", file=sys.stderr)
print("\nИтоговое состояние:") if __name__ == "__main__":
print(state) main()