Terry Zhuo commited on
Commit
fcd3706
·
1 Parent(s): 3691388
Files changed (2) hide show
  1. app.py +109 -26
  2. utils.py +27 -1
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
- sytem_prompt, user_input, max_new_tokens, model, files, message_history, request: gr.Request
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
- client = InferenceClient(api_key=HF_TOKEN)
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 message_history if it doesn't exist
67
  if len(message_history) == 0:
68
- message_history.append(
69
- {
70
- "role": "system",
71
- "content": sytem_prompt.format("- " + "\n- ".join(filenames)),
72
- }
73
- )
74
  message_history.append({"role": "user", "content": user_input})
75
 
76
- print("history:", message_history)
 
 
77
 
78
- for notebook_html, notebook_data, messages in run_interactive_notebook(
79
- client, model, tokenizer, message_history, sbx, max_new_tokens=max_new_tokens
80
- ):
81
- message_history = messages
82
 
83
- yield notebook_html, message_history, TMP_DIR+"jupyter-agent.ipynb"
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="meta-llama/Llama-3.1-8B-Instruct",
149
  choices=[
150
- "meta-llama/Llama-3.2-3B-Instruct",
151
- "meta-llama/Llama-3.1-8B-Instruct",
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