Solution ready: update agent.py

This commit is contained in:
2026-06-02 11:25:11 +00:00
parent 10b0597222
commit 3631a1c7f4
+93 -21
View File
@@ -1,45 +1,117 @@
""" """
Simple LangChain agent demonstrating HumanintheLoop middleware. HumanintheLoop agent with tool calling.
The chain: This example demonstrates how to use LangChain's `HumanInTheLoopMiddleware` to pause the agent when a tool is about to be called, ask the user for approval, and then resume execution.
1. User prompt is passed to a PromptTemplate.
2. The template is processed by an LLM (OpenAI).
3. The output passes through the HIL middleware which prints the assistants answer and asks the user to confirm or modify it before returning.
Run with: The agent uses a simple `get_weather` tool that returns a hardcoded weather string. In a real project you would replace it with an API call.
Run:
python agent.py python agent.py
Make sure you have OPENAI_API_KEY set in your environment. Make sure you have `OPENAI_API_KEY` set in your environment.
""" """
import os import os
from langchain.prompts import PromptTemplate from typing import List, Dict
from langchain.schema import RunnableSequence
from langchain_openai import ChatOpenAI
from langchain.middleware.hil import HumanInTheLoopMiddleware
from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware
from langchain.tools import BaseTool
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.types import Command
# --- Tool ---------------------------------------------------------------
class GetWeatherTool(BaseTool):
name: str = "get_weather"
description: str = "Get the weather for a city on a given date."
def _run(self, city: str, date: str) -> str:
return f"The weather in {city} on {date} is sunny with a high of 25°C."
# --- LLM ---------------------------------------------------------------
api_key = os.getenv("OPENAI_API_KEY") api_key = os.getenv("OPENAI_API_KEY")
if not api_key: if not api_key:
raise RuntimeError("OPENAI_API_KEY environment variable is required.") raise RuntimeError("OPENAI_API_KEY environment variable is required.")
llm = OpenAI(api_key=api_key, temperature=0.7) llm = ChatOpenAI(api_key=api_key, temperature=0.7)
prompt_template = PromptTemplate( # --- Agent --------------------------------------------------------------
input_variables=["question"], memory = InMemorySaver()
template="You are a helpful assistant. Answer the following question clearly and concisely: {question}"
agent = create_agent(
model=llm,
tools=[GetWeatherTool()],
system_prompt="You are a helpful assistant.",
middleware=[
HumanInTheLoopMiddleware(
interrupt_on={
"get_weather": True, # allow approve, edit, reject
},
description_prefix="Подтвердите вызов инструмента",
),
],
checkpointer=memory,
) )
chain = RunnableSequence([prompt_template, llm]) # --- Interactive loop -----------------------------------------------
hil_chain = HumanInTheLoopMiddleware(chain)
if __name__ == "__main__": if __name__ == "__main__":
config = {"configurable": {"thread_id": "session-1"}}
while True: while True:
try: try:
user_input = input("\nUser: ") try:
user_input = input("\nUser: ")
except EOFError:
print("\nNo input provided. Exiting.")
break
if user_input.lower() in {"exit", "quit", "q"}: if user_input.lower() in {"exit", "quit", "q"}:
print("Goodbye!") print("Goodbye!")
break break
result = hil_chain.invoke({"question": user_input})
print(f"\nAssistant (confirmed): {result}\n") # First invocation
result = agent.invoke({"messages": [{"role": "human", "content": user_input}]}, config=config)
# Process interrupts until finished
while "__interrupt__" in result:
interrupt = result["__interrupt__"][0].value
action_requests = interrupt.get("action_requests", [])
review_configs = interrupt.get("review_configs", [])
decisions: List[Dict] = []
print("\n--- Подтверждение ---")
for idx, action in enumerate(action_requests):
name = action.get("name")
args = action.get("args", {})
description = action.get("description", "")
print(f"Инструмент: {name}")
print(f"Аргументы: {args}")
if description:
print(f"Описание: {description}")
# Determine allowed decisions
allowed = ["approve", "reject"]
# Check if edit is allowed
for cfg in review_configs:
if cfg.get("name") == name:
allowed = cfg.get("allowed_decisions", allowed)
break
# Prompt user
while True:
choice = input("a = approve, r = reject: ").strip().lower()
if choice == "a" and "approve" in allowed:
decisions.append({"type": "approve"})
break
if choice == "r" and "reject" in allowed:
msg = input("Сообщение для агента (причина отказа): ")
decisions.append({"type": "reject", "message": msg})
break
print("Неверный ввод. Попробуйте снова.")
# Resume
result = agent.invoke(Command(resume={"decisions": decisions}), config=config) # Command(resume={"decisions":[…]})
# Finished
final_message = result.get("messages", [])[-1].get("content", "")
print(f"\nAssistant: {final_message}\n")
except KeyboardInterrupt: except KeyboardInterrupt:
print("\nInterrupted. Exiting.") print("\nInterrupted. Exiting.")
break break