Skip to content

Issue with the Google drive file picker #147

@Sachin-Bhat

Description

@Sachin-Bhat

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions