feat: solution for unknown
This commit is contained in:
@@ -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(
|
"""
|
||||||
|
Parse command line arguments.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Namespace: Parsed arguments containing the task text.
|
||||||
|
"""
|
||||||
|
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()
|
||||||
|
|
||||||
|
def validate_task_text(text: str) -> None:
|
||||||
|
"""
|
||||||
|
Validate that the provided task text is non-empty.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If the text is empty or consists only of whitespace.
|
||||||
|
"""
|
||||||
|
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",
|
model="openai/gpt-oss-20b",
|
||||||
base_url='https://platform.brojs.ru/jrnl-bh/api/inference/v1',
|
base_url='https://platform.brojs.ru/jrnl-bh/api/inference/v1',
|
||||||
api_key=SecretStr("jrnl_30283ab953615cbb6846ff9940a1eedce0b76d7b2f59a2394f29e74643e6a90d"),
|
api_key=SecretStr("jrnl_30283ab953615cbb6846ff9940a1eedce0b76d7b2f59a2394f29e74643e6a90d"),
|
||||||
temperature=0.7,
|
temperature=0.7,
|
||||||
)
|
)
|
||||||
|
|
||||||
# State definition
|
def main() -> None:
|
||||||
class GraphState(TypedDict):
|
"""
|
||||||
human_value: str | None
|
Main entry point of the orchestrator.
|
||||||
|
Parses arguments, validates input, initializes LLM, and prints the response.
|
||||||
# Node that triggers an interrupt with a question and options
|
"""
|
||||||
def ask_node(state: GraphState) -> dict:
|
args = parse_args()
|
||||||
return interrupt(
|
|
||||||
{
|
|
||||||
"type": "question",
|
|
||||||
"question": "Выберите вариант:",
|
|
||||||
"options": ["Опция 1", "Опция 2", "Опция 3"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# Build the graph
|
|
||||||
builder = StateGraph(GraphState)
|
|
||||||
builder.add_node("ask", ask_node)
|
|
||||||
builder.set_entry_point(START)
|
|
||||||
builder.add_edge(START, "ask")
|
|
||||||
builder.add_edge("ask", END)
|
|
||||||
|
|
||||||
graph = builder.compile(checkpointer=InMemorySaver())
|
|
||||||
|
|
||||||
# Main loop handling interrupts
|
|
||||||
state: GraphState = {"human_value": None}
|
|
||||||
while True:
|
|
||||||
result = graph.invoke(state)
|
|
||||||
if "__interrupt__" in result:
|
|
||||||
interrupt_data = result["__interrupt__"]
|
|
||||||
print(interrupt_data["question"])
|
|
||||||
for idx, opt in enumerate(interrupt_data["options"], 1):
|
|
||||||
print(f"{idx}. {opt}")
|
|
||||||
choice = input("Выберите номер: ").strip()
|
|
||||||
try:
|
try:
|
||||||
selected = interrupt_data["options"][int(choice) - 1]
|
validate_task_text(args.task_text)
|
||||||
state["human_value"] = selected
|
except ValueError as exc:
|
||||||
except (ValueError, IndexError):
|
print(f"Error: {exc}", file=sys.stderr)
|
||||||
print("Неверный выбор. Повторите.")
|
sys.exit(1)
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
print("\nИтоговое состояние:")
|
llm = init_llm()
|
||||||
print(state)
|
# Invoke the LLM with the task text
|
||||||
|
response = llm.invoke(
|
||||||
|
{"messages": [{"role": "human", "content": args.task_text}]}
|
||||||
|
)
|
||||||
|
# The result contains a list of messages; we print the content of the first AI message.
|
||||||
|
ai_message = next(
|
||||||
|
(msg for msg in response["messages"] if getattr(msg, "type", None) == "ai"),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
if ai_message:
|
||||||
|
print(ai_message.content)
|
||||||
|
else:
|
||||||
|
print("No AI response received.", file=sys.stderr)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user