capradeepgujaran commited on
Commit
71de0bf
·
verified ·
1 Parent(s): 4e3eedb

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +239 -0
app.py ADDED
@@ -0,0 +1,239 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import base64
3
+ import gradio as gr
4
+ from typing import List, Tuple, Optional, Dict, Any
5
+ from enum import Enum
6
+ from datetime import datetime
7
+ import httpx
8
+ from dataclasses import dataclass
9
+ from anthropic import Anthropic
10
+ import json
11
+
12
+ # Get API key from environment variable
13
+ ANTHROPIC_API_KEY = os.getenv('ANTHROPIC_API_KEY')
14
+ if not ANTHROPIC_API_KEY:
15
+ raise ValueError("ANTHROPIC_API_KEY environment variable must be set")
16
+
17
+ # Initialize Anthropic client
18
+ anthropic = Anthropic(api_key=ANTHROPIC_API_KEY)
19
+
20
+ @dataclass
21
+ class ToolResult:
22
+ output: Optional[str] = None
23
+ error: Optional[str] = None
24
+ base64_image: Optional[str] = None
25
+
26
+ def to_dict(self) -> Dict[str, Any]:
27
+ return {
28
+ "type": "tool_result",
29
+ "output": self.output,
30
+ "error": self.error,
31
+ "base64_image": self.base64_image
32
+ }
33
+
34
+ # Define the computer use tools
35
+ COMPUTER_USE_TOOLS = [
36
+ {
37
+ "type": "computer_20241022",
38
+ "name": "computer",
39
+ "display_width_px": 1024,
40
+ "display_height_px": 768,
41
+ "display_number": 1,
42
+ },
43
+ {
44
+ "type": "text_editor_20241022",
45
+ "name": "str_replace_editor"
46
+ },
47
+ {
48
+ "type": "bash_20241022",
49
+ "name": "bash"
50
+ }
51
+ ]
52
+
53
+ class ComputerUseDemo:
54
+ def __init__(self):
55
+ self.messages: List[Dict[str, Any]] = []
56
+ self.model = "claude-3-5-sonnet-20241022"
57
+ self.max_tokens = 4096
58
+
59
+ def validate_auth(self) -> Optional[str]:
60
+ if not ANTHROPIC_API_KEY:
61
+ return "ANTHROPIC_API_KEY environment variable is not set."
62
+ return None
63
+
64
+ def format_messages(self, chat_history: List[Tuple[str, str]]) -> List[Dict[str, Any]]:
65
+ """Convert chat history to Anthropic message format"""
66
+ formatted_messages = []
67
+ for user_msg, assistant_msg in chat_history:
68
+ formatted_messages.append({"role": "user", "content": user_msg})
69
+ if assistant_msg:
70
+ formatted_messages.append({"role": "assistant", "content": assistant_msg})
71
+ return formatted_messages
72
+
73
+ def execute_tool(self, tool_name: str, tool_input: str) -> ToolResult:
74
+ """Execute the requested tool and return results"""
75
+ try:
76
+ if tool_name == "computer":
77
+ return ToolResult(
78
+ output=f"Executed computer command: {tool_input}",
79
+ base64_image=None
80
+ )
81
+ elif tool_name == "str_replace_editor":
82
+ return ToolResult(
83
+ output=f"Executed text editor command: {tool_input}"
84
+ )
85
+ elif tool_name == "bash":
86
+ return ToolResult(
87
+ output=f"Executed bash command: {tool_input}"
88
+ )
89
+ else:
90
+ return ToolResult(
91
+ error=f"Unknown tool: {tool_name}"
92
+ )
93
+ except Exception as e:
94
+ return ToolResult(error=str(e))
95
+
96
+ def process_message(
97
+ self,
98
+ message: str,
99
+ chat_history: List[Tuple[str, str]],
100
+ system_prompt: str
101
+ ) -> Tuple[List[Tuple[str, str]], Optional[str]]:
102
+ """Process a message with proper error handling"""
103
+ if error := self.validate_auth():
104
+ return chat_history, error
105
+
106
+ try:
107
+ # Format messages for Claude
108
+ messages = self.format_messages(chat_history)
109
+ messages.append({"role": "user", "content": message})
110
+
111
+ # Create system prompt for computer use
112
+ base_system_prompt = """You have access to a computing environment through specialized tools.
113
+ Use the computer tool to interact with the GUI, the text editor for file operations,
114
+ and bash for command-line tasks. Take screenshots after significant actions and
115
+ verify the results carefully. Always handle errors gracefully and inform the user
116
+ of any issues."""
117
+
118
+ full_system_prompt = f"{base_system_prompt}\n{system_prompt}" if system_prompt else base_system_prompt
119
+
120
+ while True:
121
+ # Call Claude API with computer use enabled
122
+ response = anthropic.beta.messages.create(
123
+ model=self.model,
124
+ max_tokens=self.max_tokens,
125
+ messages=messages,
126
+ system=full_system_prompt,
127
+ tools=COMPUTER_USE_TOOLS,
128
+ betas=["computer-use-2024-10-22"]
129
+ )
130
+
131
+ # Handle tool calls
132
+ if response.stop_reason == "tool_use" and response.tool_calls:
133
+ tool_call = response.tool_calls[0]
134
+ tool_result = self.execute_tool(tool_call.name, tool_call.arguments)
135
+
136
+ # Add tool interactions to message history
137
+ messages.append({
138
+ "role": "assistant",
139
+ "content": [{"type": "tool_use", "name": tool_call.name, "input": tool_call.arguments}]
140
+ })
141
+ messages.append({
142
+ "role": "user",
143
+ "content": [tool_result.to_dict()]
144
+ })
145
+ else:
146
+ # Final response received
147
+ assistant_response = response.content[0].text
148
+ chat_history.append((message, assistant_response))
149
+ break
150
+
151
+ return chat_history, None
152
+
153
+ except Exception as e:
154
+ return chat_history, f"Error processing message: {str(e)}"
155
+
156
+ def create_demo() -> gr.Interface:
157
+ demo = ComputerUseDemo()
158
+
159
+ with gr.Blocks(title="Claude Computer Use Demo") as interface:
160
+ gr.Markdown("# Claude Computer Use Demo")
161
+ gr.Markdown("""## Security Notice
162
+ ⚠️ This demo runs in a sandboxed environment. Never provide access to sensitive
163
+ information or credentials, as Claude's behavior could be influenced by malicious content.""")
164
+
165
+ with gr.Row():
166
+ with gr.Column(scale=4):
167
+ chatbot = gr.Chatbot(
168
+ label="Chat History",
169
+ height=600,
170
+ container=True
171
+ )
172
+ with gr.Row():
173
+ msg = gr.Textbox(
174
+ label="Message",
175
+ placeholder="Type your instructions for Claude...",
176
+ lines=3,
177
+ scale=8
178
+ )
179
+ with gr.Column(scale=1):
180
+ submit = gr.Button("Send", variant="primary")
181
+ clear = gr.Button("Reset")
182
+
183
+ with gr.Column(scale=1):
184
+ system_prompt = gr.Textbox(
185
+ label="System Instructions",
186
+ lines=3,
187
+ placeholder="Add custom instructions for Claude..."
188
+ )
189
+ with gr.Accordion("Advanced Settings", open=False):
190
+ model = gr.Textbox(
191
+ label="Model",
192
+ value=demo.model,
193
+ interactive=False
194
+ )
195
+ max_tokens = gr.Slider(
196
+ label="Max Tokens",
197
+ minimum=1024,
198
+ maximum=8192,
199
+ value=demo.max_tokens,
200
+ step=1024
201
+ )
202
+
203
+ def on_message(
204
+ message: str,
205
+ chat_history: List[Tuple[str, str]],
206
+ system_prompt: str
207
+ ) -> Tuple[List[Tuple[str, str]], str]:
208
+ if not message.strip():
209
+ return chat_history, ""
210
+ new_history, error = demo.process_message(message, chat_history or [], system_prompt)
211
+ if error:
212
+ gr.Warning(error)
213
+ return new_history, ""
214
+
215
+ # Set up event handlers
216
+ msg.submit(
217
+ on_message,
218
+ inputs=[msg, chatbot, system_prompt],
219
+ outputs=[chatbot, msg]
220
+ )
221
+
222
+ submit.click(
223
+ on_message,
224
+ inputs=[msg, chatbot, system_prompt],
225
+ outputs=[chatbot, msg]
226
+ )
227
+
228
+ clear.click(
229
+ lambda: ([], ""),
230
+ outputs=[chatbot, msg]
231
+ )
232
+
233
+ return interface
234
+
235
+ # Create and launch the demo
236
+ demo = create_demo()
237
+
238
+ if __name__ == "__main__":
239
+ demo.launch(server_name="0.0.0.0", server_port=7860)