File size: 5,818 Bytes
3fd0067
 
740846d
3fd0067
 
b8a34b4
 
3fd0067
 
bdfd7a5
3fd0067
 
 
 
 
 
 
 
 
 
 
 
bdfd7a5
3fd0067
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
740846d
3fd0067
 
 
 
740846d
3fd0067
 
 
 
 
c02bb52
3fd0067
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
740846d
3fd0067
 
740846d
3fd0067
 
 
 
 
 
af3c122
3fd0067
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cb63aa0
3fd0067
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
af3c122
b8a34b4
3fd0067
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bdfd7a5
5f3d5cb
3fd0067
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
181
182
import base64
import os
import gradio as gr
import requests
import markdownify
from google import genai
from google.genai import types
from urllib.robotparser import RobotFileParser
from urllib.parse import urlparse

# Configure browser tools
def can_crawl_url(url: str, user_agent: str = "*") -> bool:
    """Check robots.txt permissions for a URL"""
    try:
        parsed_url = urlparse(url)
        robots_url = f"{parsed_url.scheme}://{parsed_url.netloc}/robots.txt"
        rp = RobotFileParser(robots_url)
        rp.read()
        return rp.can_fetch(user_agent, url)
    except Exception as e:
        print(f"Error checking robots.txt: {e}")
        return False

def load_page(url: str) -> str:
    """Load webpage content as markdown"""
    if not can_crawl_url(url):
        return f"URL {url} failed robots.txt check"
    try:
        response = requests.get(url, timeout=10)
        return markdownify.markdownify(response.text)
    except Exception as e:
        return f"Error loading page: {str(e)}"

# Configure Gemini client
client = genai.Client(api_key=os.environ.get("GEMINI_API_KEY"))
MODEL = "gemini-2.0-flash"
TOOLS = [
    types.Tool(
        function_declarations=[
            types.FunctionDeclaration(
                name="load_page",
                description="Load webpage content as markdown",
                parameters={
                    "type": "object",
                    "properties": {
                        "url": {"type": "string", "description": "Full URL to load"}
                    },
                    "required": ["url"]
                }
            )
        ]
    ),
    types.Tool(google_search=types.GoogleSearch()),
    types.Tool(code_execution=types.ToolCodeExecution())
]

SYSTEM_INSTRUCTION = """You are an AI assistant with multiple capabilities:
1. Web browsing through search and direct page access
2. Code execution for calculations, simulations, and data analysis
3. File I/O operations for data processing

Use this decision tree:
- For factual questions: Use search
- For time-sensitive data: Use browser tool
- For math/data processing: Generate and execute code
- Always explain your reasoning"""

def format_code_response(parts):
    """Format code execution parts for Markdown display"""
    formatted = []
    for part in parts:
        if part.text:
            formatted.append(part.text)
        if part.executable_code:
            formatted.append(f"```python\n{part.executable_code.code}\n```")
        if part.code_execution_result:
            formatted.append(f"**Result**:\n{part.code_execution_result.output}")
        if part.inline_data:
            formatted.append(f"![Generated Image](data:image/png;base64,{base64.b64encode(part.inline_data.data).decode()})")
    return "\n\n".join(formatted)

def generate_response(user_input):
    full_response = ""
    chat = client.chats.create(
        model=MODEL,
        config=types.GenerateContentConfig(
            temperature=0.7,
            tools=TOOLS,
            system_instruction=SYSTEM_INSTRUCTION
        )
    )
    
    # Initial request
    response = chat.send_message(user_input)
    
    # Process all response parts
    response_parts = []
    for part in response.candidates[0].content.parts:
        response_parts.append(part)
        full_response = format_code_response(response_parts)
        yield full_response
        
        # Handle function calls
        if part.function_call:
            fn = part.function_call
            if fn.name == "load_page":
                result = load_page(**fn.args)
                chat.send_message(
                    types.Content(
                        parts=[
                            types.Part(
                                function_response=types.FunctionResponse(
                                    name=fn.name,
                                    id=fn.id,
                                    response={"result": result}
                                )
                            )
                        ]
                    )
                )
                # Get final response after tool execution
                final_response = chat.send_message("")
                for final_part in final_response.candidates[0].content.parts:
                    response_parts.append(final_part)
                    full_response = format_code_response(response_parts)
                    yield full_response

# Gradio Interface
with gr.Blocks(title="Gemini 2.0 AI Assistant") as demo:
    gr.Markdown("# πŸš€ Gemini 2.0 AI Assistant")
    gr.Markdown("Web Access β€’ Code Execution β€’ Data Analysis")
    
    with gr.Row():
        input_box = gr.Textbox(
            label="Your Query",
            placeholder="Ask anything or request code execution...",
            lines=3,
            max_lines=10,
            autofocus=True
        )
        output_box = gr.Markdown(
            label="Assistant Response",
            elem_classes="markdown-output"
        )
    
    with gr.Row():
        submit_btn = gr.Button("Submit", variant="primary")
        clear_btn = gr.Button("Clear")
    
    def clear():
        return ["", ""]
    
    submit_btn.click(
        fn=generate_response,
        inputs=input_box,
        outputs=output_box,
        queue=True
    )
    
    clear_btn.click(
        fn=clear,
        inputs=[],
        outputs=[input_box, output_box]
    )

if __name__ == "__main__":
    demo.launch(
        server_name="0.0.0.0",
        server_port=7860,
        css="""
        .markdown-output {
            padding: 20px;
            border-radius: 5px;
            background: #f9f9f9;
        }
        .markdown-output code {
            background: #f3f3f3;
            padding: 2px 5px;
            border-radius: 3px;
        }
        """
    )