Files
2026-05-26 13:46:58 +00:00

79 lines
3.1 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Agent configuration for the HumanintheLoop example.
The agent uses :class:`langchain.agents.middleware.HumanInTheLoopMiddleware` to pause whenever a tool is called. The middleware automatically builds an interrupt payload that contains the name of the tool, its arguments and the allowed decisions (approve / reject / edit). The caller can then resume execution by sending a ``Command`` with the chosen decisions.
"""
import os
from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware
from langgraph.checkpoint.memory import MemorySaver
from langgraph.types import Command
# LLM BroJS
llm = ChatOpenAI(
model="openai/gpt-oss-20b:free",
base_url="https://platform.brojs.ru/jrnl-bh/api/inference/v1",
api_key=os.getenv("JOURNAL_MCP_PAT"),
temperature=0.5,
)
# Tool import defined in tools.py
from tools import get_weather
memory = MemorySaver()
agent = create_agent(
llm=llm,
tools=[get_weather],
system_prompt="Ты полезный ассистент.",
middleware=[
HumanInTheLoopMiddleware(
interrupt_on={"get_weather": True},
description_prefix="Подтвердите вызов инструмента",
),
],
checkpointer=memory,
)
# Helper to run a single user query with HIL loop
def run_query(user_msg: str, thread_id: str = "session-1"):
config = {"configurable": {"thread_id": thread_id}}
result = agent.invoke({"messages": [{"role": "human", "content": user_msg}]}, config)
# Loop while the agent is paused for a decision
while "__interrupt__" in result:
interrupt_value = result["__interrupt__"][0].value
action_requests = interrupt_value.get("action_requests", [])
decisions = []
print("\n--- Подтверждение вызова инструмента ---")
for idx, act in enumerate(action_requests):
name = act["name"]
args = act.get("args", {})
desc = act.get("description", "")
print(f"{idx+1}. Инструмент: {name}")
print(f" Аргументы: {args}")
if desc:
print(f" Описание: {desc}")
# Simple approve/reject per action
for idx, act in enumerate(action_requests):
while True:
choice = input("a=approve, r=reject (e=edit не поддерживается): ").strip().lower()
if choice == "a":
decisions.append({"type": "approve"})
break
elif choice == "r":
msg = input("Причина отказа: ")
decisions.append({"type": "reject", "message": msg})
break
# Resume execution with collected decisions
result = agent.invoke(Command(resume={"decisions": decisions}), config)
# Final answer
final_msg = result["messages"][-1].content
print("\nОтвет агента:")
print(final_msg)
return final_msg
if __name__ == "__main__":
run_query("Какая погода в Казани сегодня?")