Spaces:
Runtime error
Runtime error
import gradio as gr | |
import os | |
import matplotlib.pyplot as plt | |
import pandas as pd | |
from langgraph.graph import StateGraph | |
from langchain_core.messages import HumanMessage, AIMessage | |
import warnings | |
warnings.filterwarnings("ignore") | |
# Define a Command class for langgraph 0.0.41 | |
class Command: | |
def __init__(self, update=None, next=None, goto=None): | |
self.update = update or {} | |
self.next = next | |
self.goto = goto | |
# Set API key (ensure you add this as a secret in HF Spaces) | |
api_key = os.getenv("ANTHROPIC_API_KEY") | |
if not api_key: | |
raise ValueError("ANTHROPIC_API_KEY environment variable not set") | |
# Mock LLM implementation that doesn't rely on any external HTTP clients | |
class MockLLM: | |
def __init__(self): | |
self.model = "mock-model" | |
def invoke(self, inputs): | |
if isinstance(inputs, dict) and "messages" in inputs: | |
# Process the messages | |
content = "" | |
for msg in inputs["messages"]: | |
if hasattr(msg, "content"): | |
content += msg.content + "\n" | |
elif isinstance(msg, dict) and "content" in msg: | |
content += msg["content"] + "\n" | |
# For research queries | |
if "research" in content.lower(): | |
return "Based on my research, here's what I found about your topic. FINAL ANSWER: This topic shows trends that would be interesting to visualize in a chart." | |
# For chart generation | |
else: | |
return "I've analyzed the data and created a chart visualization. FINAL ANSWER: The chart shows an upward trend from 2020 to 2024." | |
elif isinstance(inputs, str): | |
if "research" in inputs.lower(): | |
return "Based on my research, here's what I found about your topic. FINAL ANSWER: This topic shows trends that would be interesting to visualize in a chart." | |
else: | |
return "I've analyzed the data and created a chart visualization. FINAL ANSWER: The chart shows an upward trend from 2020 to 2024." | |
else: | |
return "I've processed your request. FINAL ANSWER: Here's a summary of what I found." | |
# Create our mock LLM | |
llm = MockLLM() | |
# System prompt constructor | |
def make_system_prompt(suffix: str) -> str: | |
return ( | |
"You are a helpful AI assistant, collaborating with other assistants. " | |
"Use the provided tools to progress towards answering the question. " | |
"If you are unable to fully answer, that's OK—another assistant with different tools " | |
"will help where you left off. Execute what you can to make progress. " | |
"If you or any of the other assistants have the final answer or deliverable, " | |
"prefix your response with FINAL ANSWER so the team knows to stop.\n" | |
f"{suffix}" | |
) | |
# Research phase | |
def research_node(state): | |
# Create a custom research agent using langgraph 0.0.41 compatible approach | |
from langgraph.prebuilt import create_agent_executor | |
agent = create_agent_executor( | |
llm, | |
tools=[], | |
system_message=make_system_prompt("You can only do research.") | |
) | |
# Process the current state | |
result = agent.invoke(state) | |
# Check if we have a final answer | |
last_message = result["messages"][-1] | |
content = last_message.content if hasattr(last_message, "content") else last_message | |
# Create an AIMessage with the researcher name | |
if not isinstance(last_message, dict): | |
result["messages"][-1] = AIMessage(content=content, name="researcher") | |
else: | |
result["messages"][-1]["name"] = "researcher" | |
# In langgraph 0.0.41 style, return the updated state | |
return {"messages": result["messages"], "has_final_answer": "FINAL ANSWER" in content} | |
# Chart generation phase | |
def chart_node(state): | |
# Create a custom chart generator agent | |
from langgraph.prebuilt import create_agent_executor | |
agent = create_agent_executor( | |
llm, | |
tools=[], | |
system_message=make_system_prompt("You can only generate charts.") | |
) | |
# Process the current state | |
result = agent.invoke(state) | |
# Add the chart_generator name | |
last_message = result["messages"][-1] | |
content = last_message.content if hasattr(last_message, "content") else last_message | |
if not isinstance(last_message, dict): | |
result["messages"][-1] = AIMessage(content=content, name="chart_generator") | |
else: | |
result["messages"][-1]["name"] = "chart_generator" | |
# Return the updated state | |
return {"messages": result["messages"], "has_final_answer": True} | |
# Define the router function for the graph | |
def router(state): | |
# Check if we have a final answer | |
return "chart_generator" if not state.get("has_final_answer", False) else "end" | |
# Simplified end node that doesn't modify the state | |
def end_node(state): | |
return state | |
# Build a proper LangGraph for v0.0.41 | |
workflow = StateGraph({"messages": [], "has_final_answer": False}) | |
workflow.add_node("researcher", research_node) | |
workflow.add_node("chart_generator", chart_node) | |
workflow.add_node("end", end_node) | |
workflow.set_entry_point("researcher") | |
workflow.add_conditional_edges("researcher", router) | |
workflow.add_edge("chart_generator", "end") | |
graph = workflow.compile() | |
# LangGraph runner | |
def run_langgraph(user_input): | |
try: | |
# Create a human message | |
human_message = HumanMessage(content=user_input) | |
# Run the workflow with proper initialization | |
events = graph.stream({"messages": [human_message], "has_final_answer": False}) | |
outputs = list(events) | |
# Get the final message | |
final_state = outputs[-1] | |
final_messages = final_state.get("messages", []) | |
if not final_messages: | |
return "Error: No messages in the final state.", None | |
final_message = final_messages[-1] | |
final_content = final_message.content if hasattr(final_message, "content") else final_message | |
if isinstance(final_content, str) and "FINAL ANSWER" in final_content: | |
# Simulated chart (you can later parse dynamic values if needed) | |
years = [2020, 2021, 2022, 2023, 2024] | |
gdp = [21.4, 22.0, 23.1, 24.8, 26.2] | |
plt.figure() | |
plt.plot(years, gdp, marker='o') | |
plt.title("USA GDP Over Last 5 Years") | |
plt.xlabel("Year") | |
plt.ylabel("GDP in Trillions USD") | |
plt.grid(True) | |
plt.tight_layout() | |
plt.savefig("gdp_chart.png") | |
return "Chart generated based on FINAL ANSWER.", "gdp_chart.png" | |
else: | |
if isinstance(final_content, str): | |
return final_content, None | |
else: | |
return str(final_content), None | |
except Exception as e: | |
print(f"Error in run_langgraph: {e}") | |
import traceback | |
traceback.print_exc() | |
return f"Error: {str(e)}", None | |
# Gradio UI | |
def process_input(user_input): | |
return run_langgraph(user_input) | |
interface = gr.Interface( | |
fn=process_input, | |
inputs=gr.Textbox(label="Enter your research task"), | |
outputs=[gr.Textbox(label="Output"), gr.Image(type="filepath", label="Chart")], | |
title="LangGraph Research Automation", | |
description="Enter a research prompt and view chart output when applicable." | |
) | |
if __name__ == "__main__": | |
interface.launch() |