File size: 6,161 Bytes
9b5b26a
 
 
 
c19d193
6aae614
8fe992b
9b5b26a
 
2aa7c97
f08ae6c
b128c27
d3f08c6
2aa7c97
 
 
5b0b847
38d2250
b6a3811
38d2250
3ce2e03
 
 
 
 
 
 
38d2250
2aa7c97
5b0b847
 
2aa7c97
9b5b26a
0fd3147
f84e6bc
 
 
9b5b26a
37eaae3
f84e6bc
 
 
37eaae3
9b5b26a
0fd3147
3ce2e03
37eaae3
 
 
 
 
 
0bbdf93
37eaae3
0fd3147
3ce2e03
 
37eaae3
 
0fd3147
 
3ce2e03
 
 
 
 
 
 
 
 
 
 
 
 
 
37eaae3
3ce2e03
 
 
37eaae3
3ce2e03
 
37eaae3
 
3ce2e03
 
37eaae3
 
 
3ce2e03
 
 
37eaae3
9b5b26a
08bbcc6
 
55406e9
08bbcc6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9b5b26a
 
 
 
 
 
 
 
 
 
 
 
 
 
8c01ffb
 
6aae614
486ab5d
ae7a494
 
f2f8832
ae7a494
e121372
bf6d34c
 
f2f8832
fe328e0
13d500a
8c01ffb
 
9b5b26a
 
8c01ffb
861422e
 
76ea624
 
8c01ffb
8fe992b
1a77a6c
8c01ffb
 
 
 
 
 
8500fc9
8fe992b
 
9b5b26a
8c01ffb
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
157
158
159
160
161
162
163
from smolagents import CodeAgent,DuckDuckGoSearchTool, HfApiModel,load_tool,tool
import datetime
import requests
import pytz
import yaml
from tools.final_answer import FinalAnswerTool

from Gradio_UI import GradioUI

from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
from google.oauth2 import service_account
import os
from dotenv import load_dotenv
import uuid


# Google Books API setup with Service Account
json_key_path: str = "/home/user/app/audiobookagent-aaf910cd6329.json" 
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = json_key_path
try:
    credentials = service_account.Credentials.from_service_account_file(
        json_key_path,
        scopes=["https://www.googleapis.com/auth/books"]
    )
except FileNotFoundError:
    raise FileNotFoundError(f"JSON key file not found at {json_key_path}. Please upload it to /app/.")
books_service = build("books", "v1", credentials=credentials)



# I want to try connect to a google API to get some recommendation of audiobooks!
@tool
def search_audiobooks(topic: str, limit: int = 3) -> list[dict[str, any]]:
    """
    Search Google Play Books for audiobooks by topic.
    
    Args:
        topic (str): Genre or topic to search (e.g., "science").
        limit (int): Maximum number of results to return (default: 3).
    
    Returns:
        List[Dict[str, Any]]: List of audiobook metadata dictionaries.
    """
    audiobooks: list[dict[str, any]] = []
    queries: list[str] = [f"{topic}", f"audiobook {topic}", "fiction audiobook"]  # Broad queries
    
    for query in queries:
        try:
            request = books_service.volumes().list(
                q=query,
                maxResults=limit,
                printType="books"
            )
            response: dict[str, any] = request.execute()
            with open("debug_log.txt", "a") as f:
                f.write(f"API response for query '{query}': {json.dumps(response.get('items', []), indent=2)}\n")
            
            for item in response.get("items", []):
                volume_info: dict[str, any] = item.get("volumeInfo", {})
                categories: list[str] = volume_info.get("categories", [])
                title: str = volume_info.get("title", "")
                description: str = volume_info.get("description", "")
                with open("debug_log.txt", "a") as f:
                    f.write(f"Item: title='{title}', categories={categories}, description='{description[:100]}...'\n")
                
                # No filtering: return all results for debugging
                audiobooks.append({
                    "title": title or "Unknown",
                    "author": ", ".join(volume_info.get("authors", ["Unknown"])),
                    "categories": ", ".join(categories or ["Unknown"]),
                    "url": volume_info.get("canonicalVolumeLink", "#"),
                    "estimated_minutes": volume_info.get("pageCount", 180)
                })
            
            if audiobooks:
                with open("debug_log.txt", "a") as f:
                    f.write(f"Found {len(audiobooks)} audiobooks for query '{query}'\n")
                break
        except HttpError as e:
            with open("debug_log.txt", "a") as f:
                f.write(f"Google Books API error for query '{query}': {e}\n")
            continue
        except Exception as e:
            with open("debug_log.txt", "a") as f:
                f.write(f"Unexpected error in search_audiobooks for query '{query}': {e}\n")
            continue
    
    if not audiobooks:
        with open("debug_log.txt", "a") as f:
            f.write(f"No audiobooks found for topic: {topic} across all queries\n")
    return audiobooks[:limit]


@tool
# Function to estimate if audiobook fits time constraint
def filter_by_time(audiobooks: list[dict[str, any]], free_time: str) -> list[dict[str, any]]:
    """The tool is designed to match the time in terms of duration of the audiobook which is called estimated_minutes and the free time that the person have 
    Args:
        audiobooks: the list of the audiobooks
        free_time: The free time the person inform
    """
    try:
        if "hour" in free_time.lower():
            hours = float(free_time.split()[0])
            max_minutes = hours * 60
        else:
            max_minutes = float(free_time.split()[0])
    except:
        max_minutes = 180  # Default to 3 hours
    return [book for book in audiobooks if book["estimated_minutes"] <= max_minutes]

@tool
def get_current_time_in_timezone(timezone: str) -> str:
    """A tool that fetches the current local time in a specified timezone.
    Args:
        timezone: A string representing a valid timezone (e.g., 'America/New_York').
    """
    try:
        # Create timezone object
        tz = pytz.timezone(timezone)
        # Get current time in that timezone
        local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
        return f"The current local time in {timezone} is: {local_time}"
    except Exception as e:
        return f"Error fetching time for timezone '{timezone}': {str(e)}"


final_answer = FinalAnswerTool()


# If the agent does not answer, the model is overloaded, please use another model or the following Hugging Face Endpoint that also contains qwen2.5 coder:
#model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud' 

model = HfApiModel(
max_tokens=2096,
temperature=0.5,
model_id='Qwen/Qwen2.5-Coder-32B-Instruct',# it is possible that this model may be overloaded
custom_role_conversions=None,
)


# Import tool from Hub
image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)

with open("prompts.yaml", 'r') as stream:
    prompt_templates = yaml.safe_load(stream)


agent = CodeAgent(
    model=model,
    tools=[search_audiobooks,get_current_time_in_timezone,filter_by_time,final_answer], ## add your tools here (don't remove final answer)
    max_steps=6,
    verbosity_level=1,
    grammar=None,
    planning_interval=None,
    name=None,
    description=None,
    prompt_templates=prompt_templates 
)


GradioUI(agent).launch()