Gabriel CHUA commited on
Commit
1e4764f
β€’
1 Parent(s): b9ce40a

first commit

Browse files
Files changed (4) hide show
  1. README.md +40 -1
  2. app.py +236 -0
  3. config.py +30 -0
  4. requirements.txt +3 -0
README.md CHANGED
@@ -1 +1,40 @@
1
- # gradio-canvas
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Gradio Canvas πŸ€—
2
+
3
+ Gradio Canvas is a web application inspired by ChatGPT's Canvas. This project combines the capabilities of Fireworks AI and Instructor to create a seamless code generation experience.
4
+
5
+ Built with:
6
+ - Llama 3.1 405B via [Fireworks AI](https://fireworks.ai)
7
+ - [Instructor](https://github.com/instructor-ai/instructor) for structured output parsing
8
+ - [Gradio](https://github.com/gradio-app/gradio) for the web interface
9
+
10
+ ## Getting Started
11
+
12
+ ### Prerequisites
13
+
14
+ - Fireworks AI API key
15
+
16
+ ### Installation
17
+
18
+ 1. Clone the repository:
19
+ ```bash
20
+ git clone https://github.com/yourusername/gradio-canvas.git
21
+ cd gradio-canvas
22
+ ```
23
+
24
+ 2. Install the required dependencies:
25
+ ```bash
26
+ pip install -r requirements.txt
27
+ ```
28
+
29
+ 3. Set up your Fireworks AI API key as an environment variable:
30
+ ```bash
31
+ export FIREWORKS_API_KEY=your_api_key_here
32
+ ```
33
+
34
+ ### Usage
35
+
36
+ Run the application:
37
+
38
+ ```bash
39
+ gradio app.py
40
+ ```
app.py ADDED
@@ -0,0 +1,236 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ app.py
3
+ """
4
+
5
+ # Standard library imports
6
+ import json
7
+ from typing import Tuple
8
+
9
+ # Third-party imports
10
+ import gradio as gr
11
+ import instructor
12
+ from fireworks.client import Fireworks
13
+ from pydantic import BaseModel, ValidationError
14
+
15
+ # Local imports
16
+ from config import (
17
+ APP_HEADER,
18
+ APP_TITLE,
19
+ FIREWORKS_API_KEY,
20
+ LLM_MAX_TOKENS,
21
+ LLM_MODEL,
22
+ LLM_SYSTEM_PROMPT,
23
+ )
24
+
25
+
26
+ # Initialize Instructor with the Fireworks client
27
+ client = Fireworks(api_key=FIREWORKS_API_KEY)
28
+ client = instructor.from_fireworks(client)
29
+
30
+
31
+ # Define response models for feedback and code using Pydantic
32
+ class CodeResponse(BaseModel):
33
+ """Code Response"""
34
+
35
+ planning: str
36
+ full_python_code: str
37
+ commentary: str
38
+
39
+
40
+ def get_llm_responses(
41
+ user_input: str, conversation: list, current_code: str = None
42
+ ) -> Tuple[list, str, str]:
43
+ """
44
+ Generates feedback and code based on user input using the Instructor LLM.
45
+
46
+ Args:
47
+ user_input (str): The input text from the user.
48
+ conversation (list): The conversation history.
49
+ current_code (str, optional): Existing code if any.
50
+
51
+ Returns:
52
+ Tuple[list, str, str]: A tuple containing updated conversation, generated code, and formatted conversation history.
53
+ """
54
+ try:
55
+ # Update conversation history with user input
56
+ conversation.append(
57
+ {
58
+ "role": "user",
59
+ "content": (
60
+ user_input
61
+ if current_code is None
62
+ else f"{user_input} And here is the existing code: {current_code}"
63
+ ),
64
+ }
65
+ )
66
+
67
+ # Generate Feedback
68
+ feedback_resp = client.chat.completions.create(
69
+ model=LLM_MODEL,
70
+ response_model=CodeResponse,
71
+ max_tokens=LLM_MAX_TOKENS,
72
+ messages=conversation,
73
+ )
74
+
75
+ code = feedback_resp.full_python_code
76
+
77
+ # Update conversation history with assistant response
78
+ conversation.append(
79
+ {
80
+ "role": "assistant",
81
+ "content": feedback_resp.model_dump_json(),
82
+ }
83
+ )
84
+
85
+ # Format conversation history for display
86
+ conversation_text = ""
87
+
88
+ conversation_to_print = conversation[1:]
89
+
90
+ round_number = (
91
+ len(conversation_to_print) // 2
92
+ ) # Assuming each round has a user and assistant message
93
+
94
+ # Add the latest conversation pair to the top
95
+ if len(conversation_to_print) >= 2:
96
+ latest_pair = conversation_to_print[-2:]
97
+ conversation_text += f"## Version {round_number}\n\n"
98
+ for message in latest_pair:
99
+ if message["role"] != "system":
100
+ role = message["role"].capitalize()
101
+ try:
102
+ content = json.loads(message["content"])
103
+ content = content["commentary"]
104
+ except:
105
+ content = message["content"].split(
106
+ " And here is the existing code:"
107
+ )[0]
108
+ if content == "":
109
+ content = "_User edited the code directly_"
110
+
111
+ emoji = "πŸ‘€" if role == "User" else "πŸ€–"
112
+ conversation_text += f"**{emoji} {role}:** {content}\n\n"
113
+
114
+ # Add the rest of the conversation history
115
+ for i, message in enumerate(conversation_to_print[:-2]):
116
+ if message["role"] != "system":
117
+ if i % 2 == 0:
118
+ round_number = (len(conversation_to_print) - i) // 2
119
+ conversation_text += f"## Version {round_number-1}\n\n"
120
+
121
+ role = message["role"].capitalize()
122
+ try:
123
+ content = json.loads(message["content"])
124
+ content = content["commentary"]
125
+ except:
126
+ content = message["content"].split(
127
+ " And here is the existing code:"
128
+ )[0]
129
+ if content == "":
130
+ content = "_User edited the code directly_"
131
+
132
+ emoji = "πŸ‘€" if role == "User" else "πŸ€–"
133
+ conversation_text += f"**{emoji} {role}:** {content}\n\n"
134
+
135
+ return conversation, code, conversation_text
136
+
137
+ except ValidationError as ve:
138
+ error_msg = f"Response validation error: {ve}"
139
+ raise gr.Error(error_msg)
140
+ except Exception as e:
141
+ error_msg = f"An error occurred: {e}"
142
+ raise gr.Error(error_msg)
143
+
144
+
145
+ # Define the Gradio interface
146
+ with gr.Blocks(
147
+ title=APP_TITLE, theme=gr.themes.Ocean(), fill_width=True, fill_height=True
148
+ ) as demo:
149
+ gr.HTML(APP_HEADER)
150
+
151
+ with gr.Row():
152
+ with gr.Column(scale=1):
153
+ conversation_output = gr.Markdown(label="Chat History", height=500)
154
+
155
+ with gr.Column(scale=2):
156
+ code_output = gr.Code(
157
+ label="LLM Generated Code",
158
+ interactive=True,
159
+ language="python",
160
+ lines=30,
161
+ )
162
+ with gr.Row():
163
+ add_comments_btn = gr.Button("Add Comments πŸ’¬")
164
+ refactor_btn = gr.Button("Refactor πŸ”¨")
165
+
166
+ with gr.Row():
167
+ with gr.Column(scale=9):
168
+ user_input = gr.Textbox(
169
+ label="Enter Your Request here",
170
+ placeholder="Type something here...",
171
+ lines=2,
172
+ )
173
+ with gr.Column(scale=1):
174
+ submit_btn = gr.Button("Submit πŸš€")
175
+ reset_btn = gr.Button("Reset πŸ”„")
176
+
177
+ # Initialize conversation history with system prompt using Gradio State
178
+ initial_conversation = [
179
+ {
180
+ "role": "system",
181
+ "content": LLM_SYSTEM_PROMPT,
182
+ }
183
+ ]
184
+
185
+ conversation_state = gr.State(
186
+ initial_conversation
187
+ ) # Define a single State instance
188
+
189
+ # Define the button click event
190
+ def on_submit(user_input, conversation, current_code):
191
+ result = get_llm_responses(user_input, conversation, current_code)
192
+ return [""] + list(result) # Clear the textbox by returning an empty string
193
+
194
+ submit_btn.click(
195
+ fn=on_submit,
196
+ inputs=[user_input, conversation_state, code_output],
197
+ outputs=[user_input, conversation_state, code_output, conversation_output],
198
+ )
199
+
200
+ def add_comments_fn(conversation, current_code):
201
+ return on_submit(
202
+ "Please add more comments to the code. Make it production ready.",
203
+ conversation,
204
+ current_code,
205
+ )
206
+
207
+ add_comments_btn.click(
208
+ fn=add_comments_fn,
209
+ inputs=[conversation_state, code_output],
210
+ outputs=[user_input, conversation_state, code_output, conversation_output],
211
+ )
212
+
213
+ def refactor_fn(conversation, current_code):
214
+ return on_submit(
215
+ "Please refactor the code. Make it more efficient.",
216
+ conversation,
217
+ current_code,
218
+ )
219
+
220
+ refactor_btn.click(
221
+ fn=refactor_fn,
222
+ inputs=[conversation_state, code_output],
223
+ outputs=[user_input, conversation_state, code_output, conversation_output],
224
+ )
225
+
226
+ def reset_fn():
227
+ return "", initial_conversation, "", ""
228
+
229
+ reset_btn.click(
230
+ fn=reset_fn,
231
+ outputs=[user_input, conversation_state, code_output, conversation_output],
232
+ )
233
+
234
+ # Launch the Gradio app
235
+ if __name__ == "__main__":
236
+ demo.launch()
config.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ constants.py
3
+ """
4
+
5
+ import os
6
+
7
+ APP_TITLE = "πŸ€— Gradio Canvas"
8
+
9
+ APP_HEADER = """
10
+ <div style="text-align: center;">
11
+ <h1>πŸ€— Gradio Canvas</h1>
12
+ <p> Powered by <a href="https://fireworks.ai">Fireworks AI</a> πŸŽ† and <a href="https://github.com/instructor-ai/instructor">Instructor</a> πŸ‘¨β€πŸ«</p>
13
+ </div>
14
+ """
15
+
16
+ FIREWORKS_API_KEY = os.getenv("FIREWORKS_API_KEY")
17
+
18
+ LLM_MAX_TOKENS = 16_384
19
+
20
+ LLM_MODEL = "accounts/fireworks/models/llama-v3p1-405b-instruct"
21
+
22
+ LLM_SYSTEM_PROMPT = """
23
+ Your goal is to generate Python code based on the user's request.
24
+
25
+ You will receive a user request and optionally some existing code.
26
+
27
+ You MUST return your response as a JSON with the following fields: `planning`, `full_python_code`, `commentary`.
28
+
29
+ The `full_python_code` should be a complete Python script that can be executed - no code blocks or other formatting.
30
+ """
requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ fireworks-ai==0.15.6
2
+ gradio==5.1.0
3
+ instructor==1.6.3