File size: 5,224 Bytes
10e9b7d
 
eccf8e4
3c4371f
9e0b740
2c27ada
 
54756e4
2c27ada
35fd2f0
2c27ada
62f94f2
35fd2f0
 
2c27ada
 
 
 
54756e4
2c27ada
 
 
35fd2f0
2c27ada
54756e4
 
35fd2f0
 
54756e4
62f94f2
54756e4
35fd2f0
54756e4
 
35fd2f0
 
 
54756e4
35fd2f0
54756e4
3cdd433
2c27ada
3d05016
54756e4
 
35fd2f0
2c27ada
9e0b740
3db6293
e80aab9
bdd0210
31243f4
bdd0210
 
7f1f76c
 
fb46e66
54756e4
fb46e66
35fd2f0
fb46e66
 
 
7f1f76c
54756e4
fb46e66
2c27ada
fb46e66
35fd2f0
fb46e66
 
bdd0210
71d5963
7f1f76c
fb46e66
7f1f76c
71d5963
54756e4
fb46e66
35fd2f0
54756e4
 
 
7f1f76c
fb46e66
 
2c27ada
71d5963
54756e4
9e0b740
 
 
2c27ada
9e0b740
 
513d33a
7e4a06b
bdd0210
31243f4
fb46e66
 
2c27ada
31243f4
2c27ada
bdd0210
eccf8e4
62f94f2
bdd0210
2c27ada
bed6a1e
2c27ada
e80aab9
2c27ada
 
bdd0210
62f94f2
 
2c27ada
 
9e0b740
3d05016
62f94f2
3d05016
2c27ada
62f94f2
2c27ada
35fd2f0
e80aab9
 
3d05016
2c27ada
bdd0210
 
2c27ada
62f94f2
 
2c27ada
bdd0210
3d05016
 
62f94f2
 
bed6a1e
2c27ada
e80aab9
54756e4
 
9e0b740
2c27ada
 
 
3d05016
2c27ada
e80aab9
 
fb46e66
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import os
import gradio as gr
import requests
import pandas as pd
from typing import Optional
from smolagents import CodeAgent, OpenAIServerModel, tool

# --- 搜尋工具 (防封鎖增強版) ---
try:
    from duckduckgo_search import DDGS
except ImportError:
    import os
    os.system('pip install duckduckgo-search>=6.0.0')
    from duckduckgo_search import DDGS

@tool
def web_search(query: str) -> str:
    """
    Performs a web search using DuckDuckGo with anti-blocking measures.
    Args:
        query: The search query string.
    """
    print(f"🕵️ [Debug] Searching: {query}")
    try:
        # 關鍵修正:使用 backend='html' 模式,這比 API 模式更不容易被封鎖
        # 限制 max_results=3 以節省讀取時間
        with DDGS() as ddgs:
            results = ddgs.text(query, max_results=3, backend="html")
        
        if not results:
            return "No search results found. Try simpler keywords."
            
        # 格式化結果給模型看
        formatted = []
        for r in results:
            title = r.get('title', 'No Title')
            body = r.get('body', 'No Description')
            formatted.append(f"Title: {title}\nSnippet: {body}")
            
        return "\n---\n".join(formatted)
        
    except Exception as e:
        print(f"❌ Search Error: {e}")
        # 回傳錯誤訊息而不是讓程式崩潰,讓模型有機會猜測
        return f"Search failed. Please ignore search and answer based on your knowledge."

# -----------------------------------------------------------

DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"

class GroqAgent:
    def __init__(self):
        self.api_key = os.getenv("GROQ_API_KEY")
        if not self.api_key:
            self.agent = None
            return
            
        # 🏆 使用 Groq 目前最強的 Llama 3.3 70B 模型
        model = OpenAIServerModel(
            model_id="llama-3.3-70b-versatile",
            api_base="https://api.groq.com/openai/v1",
            api_key=self.api_key
        )
        
        # Agent 設定
        self.agent = CodeAgent(
            tools=[web_search], 
            model=model,
            max_steps=3, 
            verbosity_level=1
        )
    
    def __call__(self, question: str) -> str:
        if self.agent is None:
            return "Error: GROQ_API_KEY not configured."
        
        try:
            # 提示詞優化:明確告訴它如果搜尋失敗該怎麼做
            prompt = f"""
            You are a helpful assistant. Answer the question concisely.
            1. Use the 'web_search' tool to find specific facts (names, dates, numbers).
            2. If the search returns "No results" or fails, DO NOT retry endlessly. Just give your best guess immediately.
            3. For questions about images/audio you cannot see, search for the description text provided in the question.
            
            Question: {question}
            """
            return str(self.agent.run(prompt))
        except Exception as e:
            return f"Error processing request: {str(e)[:150]}"

def run_and_submit_all(profile: Optional[gr.OAuthProfile] = None):
    if profile is None:
        return "⚠️ Please login first!", None
    
    username = profile.username
    space_id = os.getenv("SPACE_ID", "s1144662")
    api_url = DEFAULT_API_URL
    
    try:
        agent_wrapper = GroqAgent()
        if agent_wrapper.agent is None:
            return "❌ Error: GROQ_API_KEY not found!", None
    except Exception as e:
        return f"❌ Init failed: {str(e)}", None
    
    try:
        print("Fetching questions...")
        response = requests.get(f"{api_url}/questions", timeout=30)
        questions = response.json()
    except Exception as e:
        return f"❌ Fetch failed: {str(e)}", None

    answers = []
    logs = []
    
    total = len(questions)
    for idx, item in enumerate(questions, 1):
        q = item.get("question")
        tid = item.get("task_id")
        
        print(f"🚀 [{idx}/{total}] Task: {tid}")
        
        # 執行 Agent
        ans = agent_wrapper(q)
        
        answers.append({"task_id": tid, "submitted_answer": ans})
        logs.append({"Task": tid, "Answer": str(ans)[:100]})

    try:
        print("Submitting...")
        res = requests.post(f"{api_url}/submit", json={
            "username": username,
            "agent_code": f"https://huggingface.co/spaces/{space_id}/tree/main",
            "answers": answers
        }, timeout=60)
        
        data = res.json()
        score = data.get('score', 0)
        
        msg = f"🎉 Final Score: {score}%" 
        return msg, pd.DataFrame(logs)
        
    except Exception as e:
        return f"Submit error: {str(e)}", pd.DataFrame(logs)

with gr.Blocks(title="Final Agent (Llama 3.3 + Anti-Block)") as demo:
    gr.Markdown("# 🚀 Final Agent (Llama 3.3 70B)")
    with gr.Row():
        gr.LoginButton()
        btn = gr.Button("Run Evaluation", variant="primary")
    out = gr.Textbox(label="Status")
    tab = gr.DataFrame(label="Logs")
    btn.click(run_and_submit_all, outputs=[out, tab])

if __name__ == "__main__":
    demo.launch()