|
|
import uuid |
|
|
import asyncio |
|
|
import os |
|
|
import gradio as gr |
|
|
|
|
|
from langchain_core.messages import HumanMessage, AIMessage |
|
|
|
|
|
|
|
|
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. |
|
|
""" |
|
|
|
|
|
app = session_state.get("app") |
|
|
human_resume_node = session_state.get("human_resume_node") |
|
|
|
|
|
|
|
|
|
|
|
if app is None: |
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
|
|
|
app, human_resume_node = await setup_graph() |
|
|
session_state["app"] = app |
|
|
session_state["human_resume_node"] = human_resume_node |
|
|
|
|
|
|
|
|
thread_id = session_state.get("thread_id") |
|
|
if not thread_id: |
|
|
thread_id = str(uuid.uuid4()) |
|
|
session_state["thread_id"] = thread_id |
|
|
|
|
|
|
|
|
is_message_command = session_state.get("is_message_command", False) |
|
|
|
|
|
config = { |
|
|
"configurable": {"thread_id": thread_id}, |
|
|
"recursion_limit": 100, |
|
|
} |
|
|
|
|
|
if is_message_command: |
|
|
|
|
|
app_input = human_resume_node.call_human_interrupt_agent(message) |
|
|
session_state["is_message_command"] = False |
|
|
else: |
|
|
|
|
|
app_input = {"messages": [HumanMessage(content=message)]} |
|
|
|
|
|
|
|
|
|
|
|
async for res in app.astream(app_input, config=config, stream_mode="values"): |
|
|
if "messages" in res: |
|
|
last_message = res["messages"][-1] |
|
|
|
|
|
|
|
|
|
|
|
if isinstance(last_message, AIMessage): |
|
|
yield last_message.content |
|
|
|
|
|
elif "__interrupt__" in res: |
|
|
|
|
|
interruption_message = res["__interrupt__"][0] |
|
|
session_state["is_message_command"] = True |
|
|
yield interruption_message.value |
|
|
return |
|
|
|
|
|
|
|
|
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 |
|
|
) |
|
|
|
|
|
|
|
|
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: |
|
|
|
|
|
|
|
|
create_gradio_app() |
|
|
except KeyboardInterrupt: |
|
|
print("\nShutting down Gradio app.") |
|
|
except Exception as e: |
|
|
print(f"An error occurred: {e}") |