MatteoMass's picture
add new gradio app
3b78b4e
raw
history blame
6.58 kB
import uuid
import asyncio
import os
import gradio as gr
from langchain_core.messages import HumanMessage, AIMessage
# Assuming mcpc_graph.py and its setup_graph function are in the same directory.
from mcpc_graph import setup_graph
async def chat_logic(message, history, session_state, github_repo, github_token, trello_api, trello_token, hf_token):
"""
Handles the main chat logic, including environment setup and streaming responses.
Args:
message (str): The user's input message.
history (list): The chat history managed by Gradio.
session_state (dict): A dictionary to maintain state across calls for a session.
github_repo (str): The GitHub repository (username/repo).
github_token (str): The GitHub personal access token.
trello_api (str): The Trello API key.
trello_token (str): The Trello API token.
hf_token (str): The Hugging Face API token.
Yields:
str: The bot's streaming response or an interruption message.
"""
# Retrieve the initialized graph and interrupt handler from the session state.
app = session_state.get("app")
human_resume_node = session_state.get("human_resume_node")
# If the graph is not initialized, this is the first message of the session.
# We configure the environment and set up the graph.
if app is None:
# Check if all required fields have been filled out.
if not all([github_repo, github_token, trello_api, trello_token, hf_token]):
yield "Error: Please provide all API keys and the GitHub repository in the 'API Configuration' section before starting the chat."
return
# Set environment variables for the current process.
os.environ["GITHUB_REPO"] = github_repo
os.environ["GITHUB_TOKEN"] = github_token
os.environ["TRELLO_API_KEY"] = trello_api
os.environ["TRELLO_API_TOKEN"] = trello_token
os.environ["HUGGINGFACE_API_KEY"] = hf_token
# Asynchronously initialize the graph and store it in the session state
# to reuse it for subsequent messages in the same session.
app, human_resume_node = await setup_graph()
session_state["app"] = app
session_state["human_resume_node"] = human_resume_node
# Ensure a unique thread_id for the conversation.
thread_id = session_state.get("thread_id")
if not thread_id:
thread_id = str(uuid.uuid4())
session_state["thread_id"] = thread_id
# Check if the current message is a response to a human interruption.
is_message_command = session_state.get("is_message_command", False)
config = {
"configurable": {"thread_id": thread_id},
"recursion_limit": 100,
}
if is_message_command:
# The user is providing feedback to an interruption.
app_input = human_resume_node.call_human_interrupt_agent(message)
session_state["is_message_command"] = False
else:
# A standard user message.
app_input = {"messages": [HumanMessage(content=message)]}
# Stream the graph's response.
# This revised logic handles intermediate messages and prevents duplication.
async for res in app.astream(app_input, config=config, stream_mode="values"):
if "messages" in res:
last_message = res["messages"][-1]
# We only stream content from AIMessages. Any intermediate AIMessages
# (e.g., "I will now use a tool") will be overwritten by subsequent
# AIMessages in the UI, so only the final answer is visible.
if isinstance(last_message, AIMessage):
yield last_message.content
elif "__interrupt__" in res:
# Handle interruptions where the agent needs human feedback.
interruption_message = res["__interrupt__"][0]
session_state["is_message_command"] = True
yield interruption_message.value
return # Stop the stream and wait for the user's next message.
def create_gradio_app():
"""Creates and launches the Gradio web application."""
print("Launching Gradio app...")
with gr.Blocks(theme=gr.themes.Soft(), title="LangGraph Multi-Agent Chat") as demo:
session_state = gr.State({})
gr.Markdown(
"""
# LangGraph Multi-Agent Project Manager
Interact with a multi-agent system powered by LangGraph.
You can assign tasks related to Trello and Github.
The system can be interrupted for human feedback when it needs to use a tool.
"""
)
chatbot = gr.Chatbot(
[],
elem_id="chatbot",
bubble_full_width=False,
height=600,
label="Multi-Agent Chat",
show_label=False
)
# --- FIX: Added an accordion for API keys and configuration ---
with gr.Accordion("API Configuration", open=True):
gr.Markdown("Please enter your credentials. The agent will be configured when you send your first message.")
github_repo = gr.Textbox(label="GitHub Repo", placeholder="e.g., username/repository", info="The target repository for GitHub operations.")
github_token = gr.Textbox(label="GitHub Token", placeholder="ghp_xxxxxxxxxxxx", type="password", info="A fine-grained personal access token.")
trello_api = gr.Textbox(label="Trello API Key", placeholder="Your Trello API key", info="Your API key from trello.com/power-ups/admin.")
trello_token = gr.Textbox(label="Trello Token", placeholder="Your Trello token", type="password", info="A token generated from your Trello account.")
hf_token = gr.Textbox(label="Hugging Face Token", placeholder="hf_xxxxxxxxxxxx", type="password", info="Used for tools requiring Hugging Face models.")
chat_interface = gr.ChatInterface(
fn=chat_logic,
chatbot=chatbot,
additional_inputs=[session_state, github_repo, github_token, trello_api, trello_token, hf_token],
title=None,
description=None,
)
demo.queue()
demo.launch(debug=True)
if __name__ == "__main__":
try:
# The main function to create the app is now synchronous.
# Gradio handles the async calls within the chat logic.
create_gradio_app()
except KeyboardInterrupt:
print("\nShutting down Gradio app.")
except Exception as e:
print(f"An error occurred: {e}")