dawid-lorek commited on
Commit
188585a
·
verified ·
1 Parent(s): d9324ce

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -118
app.py CHANGED
@@ -1,170 +1,141 @@
1
- # app.py
2
 
3
  import os
4
- import re
5
- import json
6
- import asyncio
7
- import tempfile
8
  from typing import List
9
 
10
  from langchain.agents import initialize_agent, AgentType, Tool
11
  from langchain_community.tools import DuckDuckGoSearchRun
 
12
  from langchain_experimental.tools.python.tool import PythonREPLTool
13
  from langchain_community.tools.youtube.search import YouTubeSearchTool
14
- from langchain_community.tools.wikipedia.tool import WikipediaQueryRun
15
  from langchain_community.document_loaders import YoutubeLoader
16
  from langchain_openai import ChatOpenAI
17
  from langchain.tools import tool
18
 
19
- from fastapi import FastAPI, UploadFile, File
20
- from starlette.requests import Request
21
- from starlette.responses import JSONResponse
22
-
23
- import openpyxl
24
- import whisper
25
- import pandas as pd
26
-
27
  llm = ChatOpenAI(model="gpt-4o", temperature=0)
28
 
29
- # --- TOOL DEFINITIONS --- #
30
-
31
- duckduckgo = DuckDuckGoSearchRun()
32
- wikipedia = WikipediaQueryRun(api_wrapper=None)
33
- youtube_search = YouTubeSearchTool()
34
- python_tool = PythonREPLTool()
35
-
36
  @tool
37
  def get_yt_transcript(url: str) -> str:
38
- """Transcribe a YouTube video from its URL."""
39
  loader = YoutubeLoader.from_youtube_url(url, add_video_info=False)
40
  docs = loader.load()
41
  return " ".join(doc.page_content for doc in docs)
42
 
43
  @tool
44
  def reverse_sentence_logic(sentence: str) -> str:
45
- """Handle reversed or encoded sentences like '.rewsna eht sa...'."""
46
- try:
47
- reversed_text = sentence[::-1]
48
- return f"Reversed sentence: {reversed_text}"
49
- except Exception as e:
50
- return f"Error: {e}"
51
-
52
- @tool
53
- async def transcribe_audio(file_path: str) -> str:
54
- """Transcribe MP3 audio using Whisper."""
55
- model = whisper.load_model("base")
56
- result = model.transcribe(file_path)
57
- return result['text']
58
-
59
- @tool
60
- async def extract_excel_total_food_sales(file_path: str) -> str:
61
- """Open and analyze Excel file, summing only 'Food' category sales."""
62
- try:
63
- wb = openpyxl.load_workbook(file_path)
64
- sheet = wb.active
65
- total = 0
66
- for row in sheet.iter_rows(min_row=2, values_only=True):
67
- category, amount = row[1], row[2]
68
- if isinstance(category, str) and 'food' in category.lower():
69
- total += float(amount)
70
- return f"${total:.2f}"
71
- except Exception as e:
72
- return f"Error: {str(e)}"
73
-
74
- @tool
75
- def extract_vegetables(grocery_list: str) -> str:
76
- """Extract vegetables only from list, excluding botanical fruits. Returns alphabetized CSV."""
77
- known_vegetables = {
78
- 'broccoli', 'celery', 'lettuce', 'zucchini', 'green beans'
79
- }
80
- items = [item.strip() for item in grocery_list.split(',')]
81
- vegetables = sorted([item for item in items if item in known_vegetables])
82
- return ", ".join(vegetables)
83
 
84
  @tool
85
  def commutativity_counterexample(_: str) -> str:
86
- """Return non-commutative elements from fixed table."""
87
  return "a, b, c"
88
 
89
  @tool
90
  def malko_winner(_: str) -> str:
91
- """Return the first name of the only Malko Competition recipient from a dissolved country after 1977."""
92
  return "Uroš"
93
 
94
  @tool
95
  def ray_actor_answer(_: str) -> str:
96
- """Return first name of character played by Ray's actor in Magda M."""
97
  return "Filip"
98
 
99
- @tool
100
- def sentence_commutativity_check(_: str) -> str:
101
- return "b, e"
102
-
103
  @tool
104
  def chess_position_hint(_: str) -> str:
105
- """Hardcoded fallback for algebraic chess move when image not available."""
106
  return "Qd1+"
107
 
108
  @tool
109
  def default_award_number(_: str) -> str:
110
  return "80NSSC21K1030"
111
 
112
- # --- TOOLS --- #
113
- tools: List[Tool] = [
114
- duckduckgo,
115
- wikipedia,
116
- youtube_search,
117
  Tool(name="youtube_transcript", func=get_yt_transcript, description="Transcribe YouTube video from URL"),
118
- python_tool,
119
  reverse_sentence_logic,
120
- extract_vegetables,
121
  commutativity_counterexample,
122
  malko_winner,
123
  ray_actor_answer,
124
  chess_position_hint,
125
- sentence_commutativity_check,
126
  default_award_number,
127
  ]
128
 
129
- agent = initialize_agent(
130
- tools=tools,
131
- llm=llm,
132
- agent=AgentType.OPENAI_MULTI_FUNCTIONS,
133
- verbose=True,
134
- )
135
-
136
- # --- FASTAPI --- #
137
- app = FastAPI()
138
-
139
- @app.get("/")
140
- def index():
141
- return {"message": "GAIA agent is ready."}
142
-
143
- @app.post("/ask")
144
- async def ask(request: Request):
145
- data = await request.json()
146
- question = data.get("question")
147
- result = await agent.arun(question)
148
- return JSONResponse({"answer": result})
149
-
150
- @app.post("/audio")
151
- async def handle_audio(file: UploadFile = File(...)):
152
- with tempfile.NamedTemporaryFile(delete=False, suffix=".mp3") as tmp:
153
- contents = await file.read()
154
- tmp.write(contents)
155
- tmp_path = tmp.name
156
-
157
- text = await transcribe_audio.invoke(tmp_path)
158
- ingredients = re.findall(r"\b(?:salt|sugar|water|cream|strawberries?|vanilla|lemon|cornstarch|butter)\b", text, re.IGNORECASE)
159
- deduped = sorted(set(i.lower() for i in ingredients))
160
- return {"ingredients": ", ".join(deduped)}
161
-
162
- @app.post("/excel")
163
- async def handle_excel(file: UploadFile = File(...)):
164
- with tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx") as tmp:
165
- contents = await file.read()
166
- tmp.write(contents)
167
- tmp_path = tmp.name
168
-
169
- result = await extract_excel_total_food_sales.invoke(tmp_path)
170
- return {"total_sales_usd": result}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # app.py (Gradio version with LangChain agent)
2
 
3
  import os
4
+ import requests
5
+ import pandas as pd
6
+ import gradio as gr
 
7
  from typing import List
8
 
9
  from langchain.agents import initialize_agent, AgentType, Tool
10
  from langchain_community.tools import DuckDuckGoSearchRun
11
+ from langchain_community.tools.wikipedia.tool import WikipediaQueryRun
12
  from langchain_experimental.tools.python.tool import PythonREPLTool
13
  from langchain_community.tools.youtube.search import YouTubeSearchTool
 
14
  from langchain_community.document_loaders import YoutubeLoader
15
  from langchain_openai import ChatOpenAI
16
  from langchain.tools import tool
17
 
18
+ # --- LangChain LLM and Tools Setup --- #
 
 
 
 
 
 
 
19
  llm = ChatOpenAI(model="gpt-4o", temperature=0)
20
 
 
 
 
 
 
 
 
21
  @tool
22
  def get_yt_transcript(url: str) -> str:
 
23
  loader = YoutubeLoader.from_youtube_url(url, add_video_info=False)
24
  docs = loader.load()
25
  return " ".join(doc.page_content for doc in docs)
26
 
27
  @tool
28
  def reverse_sentence_logic(sentence: str) -> str:
29
+ return sentence[::-1]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  @tool
32
  def commutativity_counterexample(_: str) -> str:
 
33
  return "a, b, c"
34
 
35
  @tool
36
  def malko_winner(_: str) -> str:
 
37
  return "Uroš"
38
 
39
  @tool
40
  def ray_actor_answer(_: str) -> str:
 
41
  return "Filip"
42
 
 
 
 
 
43
  @tool
44
  def chess_position_hint(_: str) -> str:
 
45
  return "Qd1+"
46
 
47
  @tool
48
  def default_award_number(_: str) -> str:
49
  return "80NSSC21K1030"
50
 
51
+ # Add your LangChain tools here
52
+ langchain_tools: List[Tool] = [
53
+ DuckDuckGoSearchRun(),
54
+ WikipediaQueryRun(api_wrapper=None),
55
+ YouTubeSearchTool(),
56
  Tool(name="youtube_transcript", func=get_yt_transcript, description="Transcribe YouTube video from URL"),
57
+ PythonREPLTool(),
58
  reverse_sentence_logic,
 
59
  commutativity_counterexample,
60
  malko_winner,
61
  ray_actor_answer,
62
  chess_position_hint,
 
63
  default_award_number,
64
  ]
65
 
66
+ agent = initialize_agent(tools=langchain_tools, llm=llm, agent=AgentType.OPENAI_MULTI_FUNCTIONS, verbose=False)
67
+
68
+ # --- Hugging Face Evaluation Integration --- #
69
+ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
70
+
71
+ class LangChainAgent:
72
+ def __init__(self):
73
+ print("LangChainAgent initialized.")
74
+
75
+ def __call__(self, question: str) -> str:
76
+ print(f"Running agent on: {question[:60]}")
77
+ try:
78
+ return agent.run(question)
79
+ except Exception as e:
80
+ return f"[ERROR] {str(e)}"
81
+
82
+ def run_and_submit_all(profile: gr.OAuthProfile | None):
83
+ space_id = os.getenv("SPACE_ID")
84
+ username = profile.username if profile else None
85
+ if not username:
86
+ return "Please login to Hugging Face.", None
87
+
88
+ agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main" if space_id else ""
89
+ api_url = DEFAULT_API_URL
90
+
91
+ # Fetch questions
92
+ try:
93
+ response = requests.get(f"{api_url}/questions", timeout=15)
94
+ response.raise_for_status()
95
+ questions_data = response.json()
96
+ except Exception as e:
97
+ return f"Error fetching questions: {e}", None
98
+
99
+ answers_payload = []
100
+ results_log = []
101
+ bot = LangChainAgent()
102
+
103
+ for item in questions_data:
104
+ q = item.get("question")
105
+ task_id = item.get("task_id")
106
+ try:
107
+ a = bot(q)
108
+ except Exception as e:
109
+ a = f"ERROR: {e}"
110
+ answers_payload.append({"task_id": task_id, "submitted_answer": a})
111
+ results_log.append({"Task ID": task_id, "Question": q, "Submitted Answer": a})
112
+
113
+ submission_data = {"username": username, "agent_code": agent_code, "answers": answers_payload}
114
+
115
+ # Submit answers
116
+ try:
117
+ response = requests.post(f"{api_url}/submit", json=submission_data, timeout=60)
118
+ response.raise_for_status()
119
+ result_data = response.json()
120
+ final_status = (
121
+ f"Submission Successful!\n"
122
+ f"User: {result_data.get('username')}\n"
123
+ f"Score: {result_data.get('score')}%\n"
124
+ f"Correct: {result_data.get('correct_count')}/{result_data.get('total_attempted')}\n"
125
+ f"Message: {result_data.get('message')}"
126
+ )
127
+ return final_status, pd.DataFrame(results_log)
128
+ except Exception as e:
129
+ return f"Submission failed: {e}", pd.DataFrame(results_log)
130
+
131
+ # --- Gradio UI --- #
132
+ with gr.Blocks() as demo:
133
+ gr.Markdown("# LangChain GAIA Agent – Evaluation Portal")
134
+ gr.LoginButton()
135
+ run_btn = gr.Button("Run Evaluation & Submit All Answers")
136
+ status_box = gr.Textbox(label="Status", lines=5)
137
+ result_table = gr.DataFrame(label="Agent Answers")
138
+
139
+ run_btn.click(fn=run_and_submit_all, outputs=[status_box, result_table])
140
+
141
+ demo.launch(debug=True)