File size: 7,591 Bytes
aca67d6
9b5b26a
0aecc76
 
c19d193
6fc9a0b
 
0aecc76
 
ce59abf
f12b87d
43be9fd
0aecc76
f12b87d
6fc9a0b
0aecc76
6fc9a0b
f12b87d
 
 
 
 
 
43be9fd
 
 
 
0aecc76
f12b87d
43be9fd
 
 
f12b87d
43be9fd
0aecc76
f12b87d
 
0aecc76
f12b87d
 
0aecc76
 
43be9fd
0aecc76
 
43be9fd
0aecc76
 
 
 
 
 
 
 
 
 
 
 
f12b87d
0aecc76
 
f12b87d
0aecc76
f12b87d
 
0aecc76
 
 
f12b87d
0aecc76
f12b87d
0aecc76
 
f12b87d
 
 
 
 
0aecc76
f12b87d
 
 
0aecc76
 
43be9fd
0aecc76
 
 
43be9fd
f12b87d
43be9fd
 
 
 
f12b87d
43be9fd
f12b87d
43be9fd
 
f12b87d
43be9fd
 
 
 
 
 
f12b87d
43be9fd
 
f12b87d
 
 
43be9fd
6aae614
f12b87d
29604a3
ae7a494
f12b87d
 
7d7ed98
f12b87d
 
 
 
 
 
 
 
 
 
 
 
 
ae7a494
aca67d6
f12b87d
aca67d6
f12b87d
 
13d500a
8c01ffb
f12b87d
 
 
 
 
 
 
 
8c01ffb
f12b87d
 
e06c620
 
 
f12b87d
 
 
b45a5f8
f12b87d
 
 
 
9b5b26a
8c01ffb
8fe992b
f12b87d
 
 
861422e
8fe992b
 
f12b87d
0aecc76
f12b87d
 
 
 
 
 
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
from smolagents import CodeAgent, DuckDuckGoSearchTool, load_tool, tool, LiteLLMModel
import datetime
import requests # Not used in the provided snippet directly, but often a common import
import pytz # Used in the commented-out example tool
import yaml
import os
import tempfile
from tools.final_answer import FinalAnswerTool # Assuming this exists in ./tools/final_answer.py
from tools.visit_webpage import VisitWebpageTool # Assuming this exists in ./tools/visit_webpage.py
from tools.web_search import DuckDuckGoSearchTool

import gradio as gr
import json # Not used directly in the provided snippet, but can be common

from typing import Dict, List, Optional, Union, Any
import re # Added for regex in Gradio UI if not already globally available

from smolagents.tools import Tool as SmolToolBase # Renamed to avoid conflict with @tool decorator
from smolagents.agent_types import AgentAudio, AgentImage, AgentText # For GradioUI output handling

from Gradio_UI import GradioUI # This will import the class from your modified file


@tool
def create_document(text: str, format: str = "docx") -> str:
    """Creates a document with the provided text and allows download.
    Args:
        text: The text content to write to the document.
        format: The output format, either 'docx', 'pdf', or 'txt'. Default is 'docx'.
    """
    try:
        temp_dir = tempfile.mkdtemp()
        file_name = "generated_document" # Consistent filename
        
        if format.lower() == "txt":
            path = os.path.join(temp_dir, f"{file_name}.txt")
            with open(path, "w", encoding="utf-8") as f:
                f.write(text)
            print(f"Document created (txt): {path}")
            return path

        elif format.lower() in ["docx", "pdf"]:
            try:
                import docx
                from docx.shared import Pt
            except ImportError:
                return (f"ERROR: To create DOCX or PDF files, the 'python-docx' package is required. "
                        f"Please install it (e.g., 'pip install python-docx'). "
                        f"You can try creating a 'txt' file instead by specifying format='txt'.")

            doc = docx.Document()
            doc.add_heading('Generated Document', 0)
            style = doc.styles['Normal']
            font = style.font
            font.name = 'Calibri'
            font.size = Pt(11)
            
            for paragraph in text.split('\n'):
                if paragraph.strip():
                    doc.add_paragraph(paragraph)
            
            docx_path = os.path.join(temp_dir, f"{file_name}.docx")
            doc.save(docx_path)
            print(f"Document created (docx): {docx_path}")

            if format.lower() == "pdf":
                try:
                    from docx2pdf import convert
                    pdf_path = os.path.join(temp_dir, f"{file_name}.pdf")
                    convert(docx_path, pdf_path)
                    print(f"Document converted to PDF: {pdf_path}")
                    return pdf_path
                except ImportError:
                    err_msg = (f"ERROR: PDF conversion requires the 'docx2pdf' package. "
                               f"Please install it (e.g., 'pip install docx2pdf'). "
                               f"Document saved as DOCX instead at: {docx_path}")
                    print(err_msg)
                    return err_msg # Or return docx_path with a note
                except Exception as e_pdf:
                    err_msg = f"Error converting DOCX to PDF: {str(e_pdf)}. Document saved as DOCX at: {docx_path}"
                    print(err_msg)
                    return err_msg # Or return docx_path
            
            return docx_path
        
        else:
            return f"Error: Unsupported format '{format}'. Supported formats are 'docx', 'pdf', 'txt'."
            
    except Exception as e:
        print(f"General error in create_document: {str(e)}")
        return f"Error creating document: {str(e)}"

@tool
def get_file_download_link(file_path: str) -> str:
    """Informs that a file is ready for download and its type. (Used by agent to tell user).
    Args:
        file_path: Path to the file that should be made available for download.
    """
    if not os.path.exists(file_path):
        print(f"get_file_download_link: File not found at {file_path}")
        return f"Error: File not found at {file_path}"
    
    _, file_extension = os.path.splitext(file_path)
    mime_types = {
        '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
        '.pdf': 'application/pdf',
        '.txt': 'text/plain',
    }
    mime_type = mime_types.get(file_extension.lower(), 'application/octet-stream')
    msg = f"File '{os.path.basename(file_path)}' is ready for download (type: {mime_type})."
    print(f"get_file_download_link: {msg}")
    return msg
        
final_answer = FinalAnswerTool()
web_search=DuckDuckGoSearchTool()
visit_webpage=VisitWebpageTool()

# Load image generation tool from Hub
try:
    image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True) # More likely correct
    # Common alternative: "agents-course/text-to-image" (uses a smaller SD model)
    # image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
    print(f"Successfully loaded image generation tool. Name: {getattr(image_generation_tool, 'name', 'N/A')}")
except Exception as e:
    print(f"Error loading image generation tool: {e}")
    print("Image generation will not be available.")
    image_generation_tool = None # Set to None if loading fails

# --- Configure LLM Model ---
# Ensure GEMINI_KEY is set in your environment variables
if not os.getenv("GEMINI_KEY"):
    print("CRITICAL: GEMINI_KEY environment variable not set. The LLM will not work.")
    # exit(1) # Or handle gracefully

model = LiteLLMModel(
    model_id="gemini/gemini-1.5-flash-latest", # Using a common and capable Gemini model
    api_key=os.getenv("GEMINI_KEY"),
    max_tokens=4096, # Max output tokens for the LLM
    temperature=0.6 # Slightly lower temperature for more factual tool use
)

# --- Load Prompts ---
prompts_file = "prompts.yaml"
if not os.path.exists(prompts_file):
    print(f"Warning: '{prompts_file}' not found. Using default agent prompts.")
    prompt_templates = None # Agent will use its defaults
else:
    with open(prompts_file, 'r') as stream:
        prompt_templates = yaml.safe_load(stream)

# --- Initialize Agent ---
agent_tools = [
    final_answer,
    web_search,
    visit_webpage,
    create_document, # This is a @tool decorated function, so it's directly usable
    get_file_download_link, # Also a @tool decorated function
]

if image_generation_tool:
    agent_tools.append(image_generation_tool)
else:
    print("Note: Image generation tool was not loaded, so it's not added to the agent.")
    
agent = CodeAgent(
    model=model,
    tools=agent_tools,
    max_steps=10, # Max iterations for the agent
    verbosity_level=1, # Set to 1 or higher to populate interaction_logs for GradioUI
    prompt_templates=prompt_templates
)

# --- Main Application Entry Point ---
if __name__ == "__main__":
    print("Starting Gradio UI...")
    # Initialize GradioUI with the agent
    # The GradioUI class should be imported from your modified Gradio_UI.py
    # Ensure Gradio_UI.py is in the same directory or python path
    ui = GradioUI(agent, file_upload_folder="uploaded_files") # Enable file uploads
    ui.launch() # share=False is default and safer for Spaces