Spaces:
Runtime error
Runtime error
Terry Zhuo
commited on
Commit
·
fcd3706
1
Parent(s):
3691388
update
Browse files
app.py
CHANGED
@@ -1,11 +1,12 @@
|
|
1 |
import os
|
2 |
import gradio as gr
|
3 |
from gradio.utils import get_space
|
4 |
-
from huggingface_hub import InferenceClient
|
5 |
from e2b_code_interpreter import Sandbox
|
6 |
from pathlib import Path
|
7 |
-
from transformers import AutoTokenizer
|
8 |
import json
|
|
|
|
|
9 |
|
10 |
if not get_space():
|
11 |
try:
|
@@ -20,6 +21,8 @@ from utils import (
|
|
20 |
run_interactive_notebook,
|
21 |
create_base_notebook,
|
22 |
update_notebook_display,
|
|
|
|
|
23 |
)
|
24 |
|
25 |
E2B_API_KEY = os.environ["E2B_API_KEY"]
|
@@ -37,9 +40,47 @@ with open(TMP_DIR+"jupyter-agent.ipynb", 'w', encoding='utf-8') as f:
|
|
37 |
with open("ds-system-prompt.txt", "r") as f:
|
38 |
DEFAULT_SYSTEM_PROMPT = f.read()
|
39 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
40 |
|
41 |
def execute_jupyter_agent(
|
42 |
-
|
43 |
):
|
44 |
if request.session_hash not in SANDBOXES:
|
45 |
SANDBOXES[request.session_hash] = Sandbox(api_key=E2B_API_KEY)
|
@@ -49,11 +90,9 @@ def execute_jupyter_agent(
|
|
49 |
os.makedirs(save_dir, exist_ok=True)
|
50 |
save_dir = os.path.join(save_dir, 'jupyter-agent.ipynb')
|
51 |
|
52 |
-
|
53 |
-
|
54 |
-
tokenizer = AutoTokenizer.from_pretrained(model)
|
55 |
-
# model = "meta-llama/Llama-3.1-8B-Instruct"
|
56 |
|
|
|
57 |
filenames = []
|
58 |
if files is not None:
|
59 |
for filepath in files:
|
@@ -63,28 +102,73 @@ def execute_jupyter_agent(
|
|
63 |
sbx.files.write(filpath.name, file)
|
64 |
filenames.append(filpath.name)
|
65 |
|
66 |
-
# Initialize
|
67 |
if len(message_history) == 0:
|
68 |
-
message_history.append(
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
}
|
73 |
-
)
|
74 |
message_history.append({"role": "user", "content": user_input})
|
75 |
|
76 |
-
|
|
|
|
|
77 |
|
78 |
-
|
79 |
-
|
80 |
-
):
|
81 |
-
message_history = messages
|
82 |
|
83 |
-
|
84 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
with open(save_dir, 'w', encoding='utf-8') as f:
|
86 |
json.dump(notebook_data, f, indent=2)
|
87 |
-
yield notebook_html, message_history, save_dir
|
88 |
|
89 |
def clear(msg_state):
|
90 |
msg_state = []
|
@@ -145,11 +229,10 @@ with gr.Blocks() as demo:
|
|
145 |
)
|
146 |
|
147 |
model = gr.Dropdown(
|
148 |
-
value="
|
149 |
choices=[
|
150 |
-
"
|
151 |
-
"
|
152 |
-
"meta-llama/Llama-3.1-70B-Instruct",
|
153 |
],
|
154 |
label="Models"
|
155 |
)
|
|
|
1 |
import os
|
2 |
import gradio as gr
|
3 |
from gradio.utils import get_space
|
|
|
4 |
from e2b_code_interpreter import Sandbox
|
5 |
from pathlib import Path
|
6 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
7 |
import json
|
8 |
+
import re
|
9 |
+
import torch
|
10 |
|
11 |
if not get_space():
|
12 |
try:
|
|
|
21 |
run_interactive_notebook,
|
22 |
create_base_notebook,
|
23 |
update_notebook_display,
|
24 |
+
update_notebook_with_cell,
|
25 |
+
update_notebook_with_markdown,
|
26 |
)
|
27 |
|
28 |
E2B_API_KEY = os.environ["E2B_API_KEY"]
|
|
|
40 |
with open("ds-system-prompt.txt", "r") as f:
|
41 |
DEFAULT_SYSTEM_PROMPT = f.read()
|
42 |
|
43 |
+
# Add this constant at the top with other constants
|
44 |
+
MAX_TURNS = 10
|
45 |
+
|
46 |
+
# Replace the client initialization with local model loading
|
47 |
+
def load_model_and_tokenizer(model_name="bigcomputer/jupycoder-7b-lora-350"):
|
48 |
+
if model_name == "bigcomputer/jupycoder-7b-lora-350":
|
49 |
+
model = AutoModelForCausalLM.from_pretrained(
|
50 |
+
model_name,
|
51 |
+
torch_dtype=torch.float16,
|
52 |
+
device_map="auto"
|
53 |
+
)
|
54 |
+
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen2.5-Coder-7B-Instruct")
|
55 |
+
else:
|
56 |
+
model = AutoModelForCausalLM.from_pretrained(
|
57 |
+
model_name,
|
58 |
+
torch_dtype=torch.float16,
|
59 |
+
device_map="auto"
|
60 |
+
)
|
61 |
+
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
62 |
+
return model, tokenizer
|
63 |
+
|
64 |
+
# Function to extract code and text from model response
|
65 |
+
def parse_model_response(response_text):
|
66 |
+
cells = []
|
67 |
+
# Split by code blocks
|
68 |
+
parts = re.split(r'(```python[\s\S]*?```)', response_text)
|
69 |
+
|
70 |
+
for part in parts:
|
71 |
+
if part.strip():
|
72 |
+
if part.startswith('```python'):
|
73 |
+
# Extract code without the markers
|
74 |
+
code = re.sub(r'```python\n|```', '', part).strip()
|
75 |
+
cells.append({"type": "code", "content": code})
|
76 |
+
else:
|
77 |
+
# Regular text becomes markdown
|
78 |
+
cells.append({"type": "markdown", "content": part.strip()})
|
79 |
+
|
80 |
+
return cells
|
81 |
|
82 |
def execute_jupyter_agent(
|
83 |
+
system_prompt, user_input, max_new_tokens, model_name, files, message_history, request: gr.Request
|
84 |
):
|
85 |
if request.session_hash not in SANDBOXES:
|
86 |
SANDBOXES[request.session_hash] = Sandbox(api_key=E2B_API_KEY)
|
|
|
90 |
os.makedirs(save_dir, exist_ok=True)
|
91 |
save_dir = os.path.join(save_dir, 'jupyter-agent.ipynb')
|
92 |
|
93 |
+
model, tokenizer = load_model_and_tokenizer(model_name)
|
|
|
|
|
|
|
94 |
|
95 |
+
# Handle file uploads
|
96 |
filenames = []
|
97 |
if files is not None:
|
98 |
for filepath in files:
|
|
|
102 |
sbx.files.write(filpath.name, file)
|
103 |
filenames.append(filpath.name)
|
104 |
|
105 |
+
# Initialize conversation
|
106 |
if len(message_history) == 0:
|
107 |
+
message_history.append({
|
108 |
+
"role": "system",
|
109 |
+
"content": system_prompt.format("- " + "\n- ".join(filenames))
|
110 |
+
})
|
|
|
|
|
111 |
message_history.append({"role": "user", "content": user_input})
|
112 |
|
113 |
+
# Create initial notebook
|
114 |
+
notebook_data = create_base_notebook([])
|
115 |
+
turn_count = 0
|
116 |
|
117 |
+
while turn_count < MAX_TURNS:
|
118 |
+
turn_count += 1
|
|
|
|
|
119 |
|
120 |
+
# Generate response
|
121 |
+
input_text = "\n".join([msg["content"] for msg in message_history])
|
122 |
+
inputs = tokenizer(input_text, return_tensors="pt").to(model.device)
|
123 |
+
|
124 |
+
outputs = model.generate(
|
125 |
+
**inputs,
|
126 |
+
max_new_tokens=max_new_tokens,
|
127 |
+
do_sample=True,
|
128 |
+
temperature=0.7,
|
129 |
+
)
|
130 |
+
response_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
131 |
+
|
132 |
+
# Parse response into cells
|
133 |
+
cells = parse_model_response(response_text)
|
134 |
+
|
135 |
+
# Process each cell
|
136 |
+
has_code = False
|
137 |
+
for cell in cells:
|
138 |
+
if cell["type"] == "code":
|
139 |
+
has_code = True
|
140 |
+
# Execute code cell
|
141 |
+
result = sbx.python.run(cell["content"])
|
142 |
+
# Add code cell and output to notebook
|
143 |
+
notebook_data = update_notebook_with_cell(notebook_data, cell["content"], result)
|
144 |
+
# Add execution result to message history
|
145 |
+
message_history.append({
|
146 |
+
"role": "assistant",
|
147 |
+
"content": cell["content"]
|
148 |
+
})
|
149 |
+
message_history.append({
|
150 |
+
"role": "user",
|
151 |
+
"content": f"Execution result:\n{result}"
|
152 |
+
})
|
153 |
+
else:
|
154 |
+
# Add markdown cell to notebook
|
155 |
+
notebook_data = update_notebook_with_markdown(notebook_data, cell["content"])
|
156 |
+
message_history.append({
|
157 |
+
"role": "assistant",
|
158 |
+
"content": cell["content"]
|
159 |
+
})
|
160 |
+
|
161 |
+
# Update display after each cell
|
162 |
+
notebook_html = update_notebook_display(notebook_data)
|
163 |
+
yield notebook_html, message_history, save_dir
|
164 |
+
|
165 |
+
# If no code was generated or we've reached max turns, stop
|
166 |
+
if not has_code or turn_count >= MAX_TURNS:
|
167 |
+
break
|
168 |
+
|
169 |
+
# Save final notebook
|
170 |
with open(save_dir, 'w', encoding='utf-8') as f:
|
171 |
json.dump(notebook_data, f, indent=2)
|
|
|
172 |
|
173 |
def clear(msg_state):
|
174 |
msg_state = []
|
|
|
229 |
)
|
230 |
|
231 |
model = gr.Dropdown(
|
232 |
+
value="bigcomputer/jupycoder-7b-lora-350",
|
233 |
choices=[
|
234 |
+
"bigcomputer/jupycoder-7b-lora-350",
|
235 |
+
"Qwen/Qwen2.5-Coder-7B-Instruct"
|
|
|
236 |
],
|
237 |
label="Models"
|
238 |
)
|
utils.py
CHANGED
@@ -317,4 +317,30 @@ def run_interactive_notebook(client, model, tokenizer, messages, sbx, max_new_to
|
|
317 |
if tokens[-1] == "<|eot_id|>":
|
318 |
break
|
319 |
|
320 |
-
yield update_notebook_display(notebook_data), notebook_data, messages
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
317 |
if tokens[-1] == "<|eot_id|>":
|
318 |
break
|
319 |
|
320 |
+
yield update_notebook_display(notebook_data), notebook_data, messages
|
321 |
+
|
322 |
+
def update_notebook_with_cell(notebook_data, code, output):
|
323 |
+
"""Add a code cell and its output to the notebook"""
|
324 |
+
cell = {
|
325 |
+
"cell_type": "code",
|
326 |
+
"execution_count": None,
|
327 |
+
"metadata": {},
|
328 |
+
"source": code.split('\n'),
|
329 |
+
"outputs": [{
|
330 |
+
"output_type": "stream",
|
331 |
+
"name": "stdout",
|
332 |
+
"text": str(output).split('\n')
|
333 |
+
}] if output else []
|
334 |
+
}
|
335 |
+
notebook_data['cells'].append(cell)
|
336 |
+
return notebook_data
|
337 |
+
|
338 |
+
def update_notebook_with_markdown(notebook_data, markdown_text):
|
339 |
+
"""Add a markdown cell to the notebook"""
|
340 |
+
cell = {
|
341 |
+
"cell_type": "markdown",
|
342 |
+
"metadata": {},
|
343 |
+
"source": markdown_text.split('\n')
|
344 |
+
}
|
345 |
+
notebook_data['cells'].append(cell)
|
346 |
+
return notebook_data
|