disLodge commited on
Commit
4fd7379
·
1 Parent(s): 6513634

Agent new agent features

Browse files
Files changed (5) hide show
  1. app.py +32 -37
  2. drive_tools.py +49 -0
  3. google_auth.py +60 -0
  4. indexer.py +14 -13
  5. requirements.txt +7 -1
app.py CHANGED
@@ -1,38 +1,33 @@
1
  import gradio as gr
2
- from indexer import run_email_agent
3
-
4
- with gr.Blocks(css="""
5
- body {background-color: #fffaf0;} /* Light creme background */
6
- .gr-textbox {min-height: 200px;} /* Make textboxes taller */
7
- """) as demo:
8
- gr.Markdown("## Tool-Based AI Email Agent")
9
-
10
- user_input = gr.Textbox(
11
- label="User Query",
12
- placeholder="Type your question here...",
13
- lines=4 # make input box slightly bigger
14
- )
15
- submit_btn = gr.Button("Run Agent")
16
-
17
- output = gr.Textbox(
18
- label="Agent Response",
19
- placeholder="The agent will respond here...",
20
- lines=10 # bigger response box
21
- )
22
-
23
- human_box = gr.Textbox(
24
- label="Human Assistance Required",
25
- visible=False
26
- )
27
-
28
- def handle_query(text):
29
- response = run_email_agent(text)
30
- return response
31
-
32
- submit_btn.click(
33
- handle_query,
34
- inputs=user_input,
35
- outputs=output
36
- )
37
-
38
- demo.launch()
 
1
  import gradio as gr
2
+ from fastapi import FastAPI, Request
3
+ from google_auth import get_auth_url, fetch_token
4
+ from agent import run_agent
5
+ import json
6
+
7
+ app = FastAPI()
8
+
9
+ @app.get("/login")
10
+ def login():
11
+ auth_url, state = get_auth_url()
12
+ return {"auth_url": auth_url}
13
+
14
+ @app.get("/auth/callback")
15
+ async def callback(request: Request):
16
+ code = request.query_params.get("code")
17
+ token_data = fetch_token(code)
18
+
19
+ with open("user_token.json", "w") as f:
20
+ json.dump(token_data, f)
21
+
22
+ return {"status": "Login successful. You may close this tab."}
23
+
24
+ def chat_interface(message):
25
+ return run_agent(message)
26
+
27
+ gradio_ui = gr.Interface(
28
+ fn=chat_interface,
29
+ inputs="text",
30
+ outputs="text"
31
+ )
32
+
33
+ app = gr.mount_gradio_app(app, gradio_ui, path="/")
 
 
 
 
 
drive_tools.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.tools import tool
2
+ from googleapiclient.discovery import build
3
+ from googleapiclient.http import MediaIoBaseDownload
4
+ from google_auth import dict_to_creds
5
+ import io
6
+ import os
7
+ import json
8
+
9
+ TOKEN_STORE = "user_token.json"
10
+
11
+ @tool
12
+ def search_and_download_doc_tool(file_name: str) -> str:
13
+ """
14
+ Searches Google Drive and downloads a document by name.
15
+ """
16
+
17
+ if not os.path.exists(TOKEN_STORE):
18
+ return "User not authenticated. Please login first."
19
+
20
+ with open(TOKEN_STORE, "r") as f:
21
+ token_data = json.load(f)
22
+
23
+ creds = dict_to_creds(token_data)
24
+ service = build("drive", "v3", credentials=creds)
25
+
26
+ results = service.files().list(
27
+ q=f"name contains '{file_name}'",
28
+ fields="files(id, name)"
29
+ ).execute()
30
+
31
+ items = results.get("files", [])
32
+
33
+ if not items:
34
+ return "No document found."
35
+
36
+ file_id = items[0]["id"]
37
+ request = service.files().get_media(fileId=file_id)
38
+
39
+ file_path = f"./downloads/{items[0]['name']}"
40
+ os.makedirs("downloads", exist_ok=True)
41
+
42
+ fh = io.FileIO(file_path, "wb")
43
+ downloader = MediaIoBaseDownload(fh, request)
44
+
45
+ done = False
46
+ while not done:
47
+ status, done = downloader.next_chunk()
48
+
49
+ return f"Downloaded to {file_path}"
google_auth.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ from google_auth_oauthlib.flow import Flow
4
+ from google.oauth2.credentials import Credentials
5
+
6
+ SCOPES = ['https://www.googleapis.com/auth/drive.readonly']
7
+
8
+ REDIRECT_URI = os.getenv("REDIRECT_URI")
9
+
10
+ def create_flow():
11
+ client_config = {
12
+ "web": {
13
+ "client_id": os.getenv("GOOGLE_CLIENT_ID"),
14
+ "client_secret": os.getenv("GOOGLE_CLIENT_SECRET"),
15
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
16
+ "token_uri": "https://oauth2.googleapis.com/token"
17
+ }
18
+ }
19
+
20
+ flow = Flow.from_client_config(
21
+ client_config,
22
+ scopes=SCOPES,
23
+ redirect_uri=REDIRECT_URI
24
+ )
25
+
26
+ return flow
27
+
28
+ def get_auth_url():
29
+ flow = create_flow()
30
+ auth_url, state = flow.authorization_url(
31
+ access_type='offline',
32
+ include_granted_scopes='true'
33
+ )
34
+ return auth_url, state
35
+
36
+ def fetch_token(code):
37
+ flow = create_flow()
38
+ flow.fetch_token(code=code)
39
+ creds = flow.credentials
40
+ return creds_to_dict(creds)
41
+
42
+ def creds_to_dict(creds):
43
+ return {
44
+ "token": creds.token,
45
+ "refresh_token": creds.refresh_token,
46
+ "token_uri": creds.token_uri,
47
+ "client_id": creds.client_id,
48
+ "client_secret": creds.client_secret,
49
+ "scopes": creds.scopes
50
+ }
51
+
52
+ def dict_to_creds(data):
53
+ return Credentials(
54
+ token=data["token"],
55
+ refresh_token=data["refresh_token"],
56
+ token_uri=data["token_uri"],
57
+ client_id=data["client_id"],
58
+ client_secret=data["client_secret"],
59
+ scopes=data["scopes"]
60
+ )
indexer.py CHANGED
@@ -14,6 +14,7 @@ from langchain_tavily import TavilySearch
14
  from langchain_groq import ChatGroq
15
  from langgraph.checkpoint.memory import MemorySaver
16
  from langgraph.types import Command, interrupt
 
17
  import os
18
 
19
 
@@ -63,7 +64,7 @@ def send_email_tool(to_email: str, subject: str, body: str) -> str:
63
  except Exception as e:
64
  return f"Failed to send email: {str(e)}"
65
 
66
- tools = [send_email_tool]
67
  llm_with_tools = llm.bind_tools(tools)
68
 
69
  # ==================== STATE =======================
@@ -77,12 +78,16 @@ graph_builder=StateGraph(State)
77
  def chatbot(state:State):
78
  response = llm_with_tools.invoke([
79
  SystemMessage(content="""
80
- You are an email assistant.
81
- When the user wants to send an email:
82
- - Extract recipient email
83
- - Generate subject
84
- - Generate professional body
85
- - ALWAYS call send_email_tool
 
 
 
 
86
  """),
87
  *state["messages"]
88
  ])
@@ -115,15 +120,11 @@ graph=graph_builder.compile()
115
 
116
  # ==================== ENTRY FUNCTION =======================
117
 
118
- def run_email_agent(user_input: str):
119
  result = graph.invoke({
120
  "messages": [HumanMessage(content=user_input)]
121
  })
122
-
123
- final_message = result["messages"][-1].content
124
- return final_message
125
-
126
-
127
 
128
  # Start
129
  # LLM + promt -> Chatbot
 
14
  from langchain_groq import ChatGroq
15
  from langgraph.checkpoint.memory import MemorySaver
16
  from langgraph.types import Command, interrupt
17
+ from drive_tools import search_and_download_doc_tool
18
  import os
19
 
20
 
 
64
  except Exception as e:
65
  return f"Failed to send email: {str(e)}"
66
 
67
+ tools = [search_and_download_doc_tool, send_email_tool]
68
  llm_with_tools = llm.bind_tools(tools)
69
 
70
  # ==================== STATE =======================
 
78
  def chatbot(state:State):
79
  response = llm_with_tools.invoke([
80
  SystemMessage(content="""
81
+ You are an AI assistant with access to tools.
82
+
83
+ Available tools:
84
+ 1. send_email_tool → Use when the user wants to send an email.
85
+ 2. search_and_download_doc_tool Use when the user wants to find or download a document from Google Drive.
86
+
87
+ Rules:
88
+ - Always call the appropriate tool when the request requires action.
89
+ - Do NOT respond with plain text if an action is required.
90
+ - After tool execution, summarize the result for the user.
91
  """),
92
  *state["messages"]
93
  ])
 
120
 
121
  # ==================== ENTRY FUNCTION =======================
122
 
123
+ def run_agent(user_input: str):
124
  result = graph.invoke({
125
  "messages": [HumanMessage(content=user_input)]
126
  })
127
+ return result["messages"][-1].content
 
 
 
 
128
 
129
  # Start
130
  # LLM + promt -> Chatbot
requirements.txt CHANGED
@@ -3,6 +3,7 @@ langchain>=0.3.0
3
  langsmith
4
  python-dotenv
5
  langchain-groq
 
6
  pandas
7
  numpy
8
  scikit-learn
@@ -17,4 +18,9 @@ langchain-core>=0.3.0
17
  langchain-community>=0.3.0
18
  langchain-openai
19
  langchain_tavily>=0.1.0
20
- langchain_huggingface>=0.1.0
 
 
 
 
 
 
3
  langsmith
4
  python-dotenv
5
  langchain-groq
6
+ gradio
7
  pandas
8
  numpy
9
  scikit-learn
 
18
  langchain-community>=0.3.0
19
  langchain-openai
20
  langchain_tavily>=0.1.0
21
+ langchain_huggingface>=0.1.0
22
+ fastapi
23
+ google-auth
24
+ google-auth-oauthlib
25
+ google-auth-httplib2
26
+ google-api-python-client