jzou19950715 commited on
Commit
37dde34
Β·
verified Β·
1 Parent(s): d5a3e79

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -99
app.py CHANGED
@@ -1,14 +1,9 @@
1
  import gradio as gr
2
  import anthropic
3
- import os
4
  from typing import List, Dict, Optional, Tuple
5
- from http import HTTPStatus
6
 
7
  # Constants
8
- MODEL_NAME = "claude-3-5-sonnet-20241022" # Updated model name
9
- MAX_TOKENS = 4096
10
- TEMPERATURE = 0.7
11
-
12
  DEFAULT_SYSTEM_PROMPT = """You are a specialized coding assistant powered by Claude 3.5 Sonnet. Your primary focus is helping with programming tasks, code review, debugging, and software architecture. You should:
13
 
14
  1. Always provide complete, production-ready code solutions
@@ -34,53 +29,35 @@ For all code examples:
34
  - Consider edge cases
35
  """
36
 
37
- class APIError(Exception):
38
- """Custom exception for API-related errors"""
39
- def __init__(self, message: str, status_code: Optional[int] = None):
40
- super().__init__(message)
41
- self.status_code = status_code
42
 
43
  class ChatState:
44
  """Manages the state of the chat session"""
45
  def __init__(self):
46
- self.client: Optional[anthropic.Anthropic] = None
47
  self.system_prompt: str = DEFAULT_SYSTEM_PROMPT
48
  self.history: List[Tuple[str, str]] = []
49
 
50
  def initialize_client(self, api_key: str) -> Tuple[bool, str]:
51
  """Initialize the Anthropic client with the provided API key"""
52
  try:
53
- # Validate API key format
54
- if not api_key.startswith('sk-'):
55
- return False, "Invalid API key format. Key should start with 'sk-'"
56
-
57
- # Initialize client with proper error handling
58
- self.client = anthropic.Anthropic(
59
- api_key=api_key,
60
- )
61
-
62
  # Test the API key with a minimal request
63
- response = self.client.messages.create(
64
- model=MODEL_NAME,
65
  max_tokens=10,
66
- messages=[
67
- {"role": "user", "content": "test"}
68
- ]
69
  )
70
-
71
- return True, "βœ… API key validated successfully!"
72
-
73
- except anthropic.APIError as e:
74
- self.client = None
75
- if e.status_code == HTTPStatus.UNAUTHORIZED:
76
- return False, "❌ Invalid API key. Please check your credentials."
77
- elif e.status_code == HTTPStatus.TOO_MANY_REQUESTS:
78
- return False, "❌ Rate limit exceeded. Please try again later."
79
- else:
80
- return False, f"❌ API Error: {str(e)}"
81
  except Exception as e:
82
  self.client = None
83
- return False, f"❌ Error: {str(e)}"
 
 
 
 
 
84
 
85
  def generate_response(self, message: str) -> str:
86
  """Generate a response using the Claude API"""
@@ -88,22 +65,18 @@ class ChatState:
88
  return "Please enter a valid API key first."
89
 
90
  try:
91
- # Construct messages including system prompt and history
92
  messages = [{"role": "system", "content": self.system_prompt}]
93
 
94
- # Add conversation history
95
  for human_msg, assistant_msg in self.history:
96
  messages.extend([
97
  {"role": "user", "content": human_msg},
98
  {"role": "assistant", "content": assistant_msg}
99
  ])
100
 
101
- # Add current message
102
  messages.append({"role": "user", "content": message})
103
 
104
- # Make API call with all recommended parameters
105
  response = self.client.messages.create(
106
- model=MODEL_NAME,
107
  max_tokens=MAX_TOKENS,
108
  temperature=TEMPERATURE,
109
  messages=messages
@@ -111,10 +84,6 @@ class ChatState:
111
 
112
  return response.content[0].text
113
 
114
- except anthropic.APIError as e:
115
- if e.status_code == HTTPStatus.TOO_MANY_REQUESTS:
116
- return "Rate limit exceeded. Please try again in a few seconds."
117
- return f"API Error: {str(e)}"
118
  except Exception as e:
119
  return f"Error generating response: {str(e)}"
120
 
@@ -127,62 +96,71 @@ def create_demo() -> gr.Blocks:
127
  chat_state = ChatState()
128
 
129
  with gr.Blocks(title="Claude Coding Assistant", theme=gr.themes.Soft()) as demo:
130
- gr.Markdown("""
131
- # Claude Coding Assistant πŸ€–πŸ’»
132
-
133
- A specialized coding assistant powered by Claude 3.5 Sonnet. Features:
134
- - Complete code solutions with best practices
135
- - Detailed explanations and documentation
136
- - Code review and optimization suggestions
137
- - Security considerations and design patterns
138
-
139
- Enter your Anthropic API key (starts with 'sk-') to begin.
140
- """)
141
-
142
- # API Key input section
143
  with gr.Row():
144
- api_key_input = gr.Textbox(
145
- label="Anthropic API Key",
146
- placeholder="sk-...",
147
- type="password",
148
- scale=4
149
- )
150
- validate_btn = gr.Button("πŸ”‘ Validate API Key", scale=1)
151
- status_text = gr.Textbox(
152
- label="Status",
153
- interactive=False,
154
- scale=2
155
- )
156
-
157
- # Chat interface
158
- chatbot = gr.Chatbot(
159
- height=600,
160
- show_label=False,
161
- container=True,
162
- show_copy_button=True,
163
- bubble_full_width=False
164
- )
165
-
166
- with gr.Row():
167
- message_input = gr.Textbox(
168
- label="Your message",
169
- placeholder="Ask me about coding, software design, or technical problems...",
170
- lines=3,
171
- scale=4
172
- )
173
- submit_btn = gr.Button("πŸš€ Send", scale=1)
174
- clear_btn = gr.Button("πŸ—‘οΈ Clear Chat", scale=1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
  # Event handlers
177
  def validate_api_key(api_key: str) -> str:
178
  success, message = chat_state.initialize_client(api_key)
179
  return message
180
 
 
 
 
181
  def respond(message: str, history: List[Tuple[str, str]]) -> Tuple[List[Tuple[str, str]], str]:
182
  if not chat_state.client:
183
- return history + [(message, "Please validate your API key first.")], ""
184
- if not message.strip():
185
- return history, ""
186
 
187
  response = chat_state.generate_response(message)
188
  chat_state.history = history + [(message, response)]
@@ -199,6 +177,12 @@ def create_demo() -> gr.Blocks:
199
  outputs=[status_text]
200
  )
201
 
 
 
 
 
 
 
202
  submit_btn.click(
203
  respond,
204
  inputs=[message_input, chatbot],
@@ -216,16 +200,16 @@ def create_demo() -> gr.Blocks:
216
  outputs=[chatbot, message_input]
217
  )
218
 
219
- # Add coding-specific examples
220
  gr.Examples(
221
  examples=[
 
222
  "Review this code for security issues:\n```python\ndef process_user_input(data):\n result = eval(data)\n return result```",
223
- "Create a TypeScript React component that implements infinite scrolling with proper error handling and loading states.",
224
- "Explain how to implement rate limiting in a distributed system using Redis, with code examples.",
225
- "Write a Python function that implements merge sort with comprehensive type hints and unit tests.",
226
  ],
227
  inputs=message_input,
228
- label="Example Coding Questions"
229
  )
230
 
231
  return demo
 
1
  import gradio as gr
2
  import anthropic
 
3
  from typing import List, Dict, Optional, Tuple
4
+ import json
5
 
6
  # Constants
 
 
 
 
7
  DEFAULT_SYSTEM_PROMPT = """You are a specialized coding assistant powered by Claude 3.5 Sonnet. Your primary focus is helping with programming tasks, code review, debugging, and software architecture. You should:
8
 
9
  1. Always provide complete, production-ready code solutions
 
29
  - Consider edge cases
30
  """
31
 
32
+ MAX_TOKENS = 4096
33
+ TEMPERATURE = 0.7
 
 
 
34
 
35
  class ChatState:
36
  """Manages the state of the chat session"""
37
  def __init__(self):
38
+ self.client: Optional[anthropic.Client] = None
39
  self.system_prompt: str = DEFAULT_SYSTEM_PROMPT
40
  self.history: List[Tuple[str, str]] = []
41
 
42
  def initialize_client(self, api_key: str) -> Tuple[bool, str]:
43
  """Initialize the Anthropic client with the provided API key"""
44
  try:
45
+ self.client = anthropic.Client(api_key=api_key)
 
 
 
 
 
 
 
 
46
  # Test the API key with a minimal request
47
+ self.client.messages.create(
48
+ model="claude-3-sonnet-20241022",
49
  max_tokens=10,
50
+ messages=[{"role": "user", "content": "test"}]
 
 
51
  )
52
+ return True, "API key validated successfully!"
 
 
 
 
 
 
 
 
 
 
53
  except Exception as e:
54
  self.client = None
55
+ return False, f"Error validating API key: {str(e)}"
56
+
57
+ def update_system_prompt(self, new_prompt: str) -> str:
58
+ """Update the system prompt"""
59
+ self.system_prompt = new_prompt
60
+ return "System prompt updated successfully!"
61
 
62
  def generate_response(self, message: str) -> str:
63
  """Generate a response using the Claude API"""
 
65
  return "Please enter a valid API key first."
66
 
67
  try:
 
68
  messages = [{"role": "system", "content": self.system_prompt}]
69
 
 
70
  for human_msg, assistant_msg in self.history:
71
  messages.extend([
72
  {"role": "user", "content": human_msg},
73
  {"role": "assistant", "content": assistant_msg}
74
  ])
75
 
 
76
  messages.append({"role": "user", "content": message})
77
 
 
78
  response = self.client.messages.create(
79
+ model="claude-3-sonnet-20241022",
80
  max_tokens=MAX_TOKENS,
81
  temperature=TEMPERATURE,
82
  messages=messages
 
84
 
85
  return response.content[0].text
86
 
 
 
 
 
87
  except Exception as e:
88
  return f"Error generating response: {str(e)}"
89
 
 
96
  chat_state = ChatState()
97
 
98
  with gr.Blocks(title="Claude Coding Assistant", theme=gr.themes.Soft()) as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  with gr.Row():
100
+ # Main chat area (2/3 width)
101
+ with gr.Column(scale=2):
102
+ gr.Markdown("""
103
+ # Claude Coding Assistant πŸ€–πŸ’»
104
+
105
+ A specialized coding assistant powered by Claude 3.5 Sonnet. Features:
106
+ - Complete code solutions with best practices
107
+ - Detailed explanations and documentation
108
+ - Code review and optimization suggestions
109
+ - Security considerations and design patterns
110
+ """)
111
+
112
+ # API Key input section
113
+ with gr.Row():
114
+ api_key_input = gr.Textbox(
115
+ label="Anthropic API Key",
116
+ placeholder="Enter your API key...",
117
+ type="password",
118
+ scale=4
119
+ )
120
+ validate_btn = gr.Button("Validate API Key", scale=1)
121
+ status_text = gr.Textbox(label="Status", interactive=False, scale=2)
122
+
123
+ # Chat interface
124
+ chatbot = gr.Chatbot(
125
+ height=600,
126
+ show_label=False,
127
+ container=True,
128
+ show_copy_button=True
129
+ )
130
+
131
+ with gr.Row():
132
+ message_input = gr.Textbox(
133
+ label="Your message",
134
+ placeholder="Ask me about coding, software design, or technical problems...",
135
+ lines=3,
136
+ scale=4
137
+ )
138
+ submit_btn = gr.Button("Send", scale=1)
139
+ clear_btn = gr.Button("Clear Chat", scale=1)
140
+
141
+ # Sidebar for system prompt (1/3 width)
142
+ with gr.Column(scale=1):
143
+ gr.Markdown("### System Prompt Editor")
144
+ system_prompt_input = gr.TextArea(
145
+ value=DEFAULT_SYSTEM_PROMPT,
146
+ label="Customize the AI's behavior",
147
+ lines=20,
148
+ placeholder="Enter system prompt..."
149
+ )
150
+ update_prompt_btn = gr.Button("Update System Prompt")
151
+ prompt_status = gr.Textbox(label="Prompt Status", interactive=False)
152
 
153
  # Event handlers
154
  def validate_api_key(api_key: str) -> str:
155
  success, message = chat_state.initialize_client(api_key)
156
  return message
157
 
158
+ def update_system_prompt(new_prompt: str) -> str:
159
+ return chat_state.update_system_prompt(new_prompt)
160
+
161
  def respond(message: str, history: List[Tuple[str, str]]) -> Tuple[List[Tuple[str, str]], str]:
162
  if not chat_state.client:
163
+ return history + [("", "Please validate your API key first.")], ""
 
 
164
 
165
  response = chat_state.generate_response(message)
166
  chat_state.history = history + [(message, response)]
 
177
  outputs=[status_text]
178
  )
179
 
180
+ update_prompt_btn.click(
181
+ update_system_prompt,
182
+ inputs=[system_prompt_input],
183
+ outputs=[prompt_status]
184
+ )
185
+
186
  submit_btn.click(
187
  respond,
188
  inputs=[message_input, chatbot],
 
200
  outputs=[chatbot, message_input]
201
  )
202
 
203
+ # Add examples
204
  gr.Examples(
205
  examples=[
206
+ "Can you help me implement a binary search tree in Python with type hints?",
207
  "Review this code for security issues:\n```python\ndef process_user_input(data):\n result = eval(data)\n return result```",
208
+ "Explain the SOLID principles with practical examples in TypeScript.",
209
+ "How would you implement rate limiting in a REST API?",
 
210
  ],
211
  inputs=message_input,
212
+ label="Example Questions"
213
  )
214
 
215
  return demo