-
Notifications
You must be signed in to change notification settings - Fork 6
Open
Description
Hi, Nice project by the way! It handles auth quite well. Was wondering if it could be made clearer on how to read the file picked from the file picker. The following is my code:
import os
# Import necessary classes and modules
from langchain_arcade import ToolManager
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import END, START, MessagesState, StateGraph
from langgraph.prebuilt import ToolNode
arcade_api_key = os.environ["ARCADE_API_KEY"]
# Initialize the tool manager and fetch tools compatible with langgraph
tool_manager = ToolManager(api_key=arcade_api_key)
tools = tool_manager.init_tools(toolkits=["Google"])
langchain_tools = tool_manager.to_langchain()
tool_node = ToolNode(langchain_tools)
# Create a language model instance and bind it with the tools
model = ChatOpenAI(model="gpt-4o")
model_with_tools = model.bind_tools(tools)
# Function to invoke the model and get a response
def call_agent(state: MessagesState):
messages = state["messages"]
response = model_with_tools.invoke(messages)
# Return the updated message history
return {"messages": [response]}
# Function to determine the next step in the workflow based on the last message
def should_continue(state: MessagesState):
if state["messages"][-1].tool_calls:
for tool_call in state["messages"][-1].tool_calls:
if tool_manager.requires_auth(tool_call["name"]):
return "authorization"
return "tools" # Proceed to tool execution if no authorization is needed
return END # End the workflow if no tool calls are present
# Function to handle authorization for tools that require it
def authorize(state: MessagesState, config: dict):
user_id = config["configurable"].get("user_id")
for tool_call in state["messages"][-1].tool_calls:
tool_name = tool_call["name"]
if not tool_manager.requires_auth(tool_name):
continue
auth_response = tool_manager.authorize(tool_name, user_id)
if auth_response.status != "completed":
# Prompt the user to visit the authorization URL
print(f"Visit the following URL to authorize: {auth_response.url}")
# Wait for the user to complete the authorization
# and then check the authorization status again
tool_manager.wait_for_auth(auth_response.id)
if not tool_manager.is_authorized(auth_response.id):
# This stops execution if authorization fails
raise ValueError("Authorization failed")
return {"messages": []}
if __name__ == "__main__":
# Build the workflow graph using StateGraph
workflow = StateGraph(MessagesState)
# Add nodes (steps) to the graph
workflow.add_node("agent", call_agent)
workflow.add_node("tools", tool_node)
workflow.add_node("authorization", authorize)
# Define the edges and control flow between nodes
workflow.add_edge(START, "agent")
workflow.add_conditional_edges("agent", should_continue, ["authorization", "tools", END])
workflow.add_edge("authorization", "tools")
workflow.add_edge("tools", "agent")
# Set up memory for checkpointing the state
memory = MemorySaver()
# Compile the graph with the checkpointer
graph = workflow.compile(checkpointer=memory)
# Define the input messages from the user
inputs = {
"messages": [
{
"role": "user",
"content": "I want to pick a file from my google drive",
}
],
}
# Configuration with thread and user IDs for authorization purposes
config = {"configurable": {"thread_id": "4", "user_id": "[email protected]"}}
# Run the graph and stream the outputs
for chunk in graph.stream(inputs, config=config, stream_mode="values"):
# Pretty-print the last message in the chunk
chunk["messages"][-1].pretty_print()
# Wait for user to pick the file
input("\nPress Enter after you have picked the file...")
# Now add the second message to read the file
inputs["messages"].append({
"role": "user",
"content": "Now I want to read the picked file",
})
# Run the graph again with the updated messages
for chunk in graph.stream(inputs, config=config, stream_mode="values"):
# Pretty-print the last message in the chunk
chunk["messages"][-1].pretty_print()
Please let me know if there is any way to expose some of the file metadata as well to tell which file was selected.
Thanks,
Sachin
lennardkorte
Metadata
Metadata
Assignees
Labels
No labels