Fabrizio (Misto) Milo commited on
Commit
10acc0a
·
1 Parent(s): ff905a4

3 columns test

Browse files
Files changed (2) hide show
  1. README.md +2 -2
  2. app.py +92 -41
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
- title: Jupyter Agent 2
3
- emoji: 🏃
4
  colorFrom: red
5
  colorTo: purple
6
  sdk: gradio
 
1
  ---
2
+ title: NBH LIVE EDITOR
3
+ emoji:
4
  colorFrom: red
5
  colorTo: purple
6
  sdk: gradio
app.py CHANGED
@@ -23,6 +23,25 @@ from utils import (
23
  run_interactive_notebook,
24
  )
25
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  E2B_API_KEY = os.environ["E2B_API_KEY"]
27
  HF_TOKEN = os.environ["HF_TOKEN"] #HfFolder.get_token() #
28
  DEFAULT_MAX_TOKENS = 512
@@ -111,7 +130,13 @@ def execute_jupyter_agent(
111
 
112
  with open(save_dir, 'w', encoding='utf-8') as f:
113
  json.dump(init_notebook.data, f, indent=2)
114
- yield init_notebook.render(), message_history, save_dir
 
 
 
 
 
 
115
 
116
  client = OpenAI(
117
  base_url="https://router.huggingface.co/v1",
@@ -149,12 +174,24 @@ def execute_jupyter_agent(
149
  client, model, message_history, sbx,
150
  ):
151
  message_history = messages
152
-
153
- yield notebook_html, message_history, TMP_DIR+"jupyter-agent.ipynb"
 
 
 
 
 
 
154
 
155
  with open(save_dir, 'w', encoding='utf-8') as f:
156
  json.dump(notebook_data, f, indent=2)
157
- yield notebook_html, message_history, save_dir
 
 
 
 
 
 
158
 
159
  def clear(msg_state, request: gr.Request):
160
  if request.session_hash in SANDBOXES:
@@ -166,55 +203,69 @@ def clear(msg_state, request: gr.Request):
166
 
167
 
168
  css = """
169
- #component-0 {
170
- height: 100vh;
171
- overflow-y: auto;
172
- padding: 20px;
173
- }
174
-
175
- .gradio-container {
176
- height: 100vh !important;
177
- }
178
-
179
- .contain {
180
- height: 100vh !important;
181
- }
182
  """
183
 
184
 
185
  # Create the interface
186
- with gr.Blocks() as demo:
187
  msg_state = gr.State(value=[])
188
 
189
- html_output = gr.HTML(value=JupyterNotebook().render())
190
-
191
- user_input = gr.Textbox(
192
- #value="Write code to multiply three numbers: 10048, 32, 19", lines=3, label="User input"
193
- value="Solve the Lotka-Volterra equation and plot the results. Do it step by step and explain what you are doing and in the end make a super nice and clean plot.", label="Agent task"
194
- )
195
-
196
- with gr.Row():
197
- generate_btn = gr.Button("Run!")
198
- clear_btn = gr.Button("Clear Notebook")
199
-
200
- with gr.Accordion("Upload files ⬆ | Download notebook⬇", open=False):
201
- files = gr.File(label="Upload files to use", file_count="multiple")
202
- file = gr.File(TMP_DIR+"jupyter-agent.ipynb", label="Download Jupyter Notebook")
203
-
204
- powered_html = gr.HTML("""\
205
- <p align="center">
206
- <img style="max-height:100px; max-width:100%; height:auto;"src="https://huggingface.co/spaces/lvwerra/jupyter-agent-2/resolve/main/powered-by.png" alt="Powered by" />
207
- </p>""")
208
-
209
-
 
 
 
 
 
 
 
 
 
 
 
 
210
  generate_btn.click(
211
  fn=execute_jupyter_agent,
212
  inputs=[user_input, files, msg_state],
213
- outputs=[html_output, msg_state, file],
 
 
 
 
 
 
214
  show_progress="hidden",
215
  )
216
 
217
- clear_btn.click(fn=clear, inputs=[msg_state], outputs=[html_output, msg_state])
 
 
 
 
218
 
219
  demo.load(
220
  fn=None,
 
23
  run_interactive_notebook,
24
  )
25
 
26
+ def _messages_to_chat_pairs(messages):
27
+ """Convert internal message history to Chatbot (user, assistant) pairs."""
28
+ pairs = []
29
+ last_user = None
30
+ for m in messages:
31
+ role = m.get("role")
32
+ if role == "user":
33
+ last_user = m.get("content", "")
34
+ elif role == "assistant":
35
+ content = m.get("content") or ""
36
+ if last_user is not None or content:
37
+ pairs.append((last_user or "", content))
38
+ last_user = None
39
+ else:
40
+ continue
41
+ if last_user is not None:
42
+ pairs.append((last_user, ""))
43
+ return pairs
44
+
45
  E2B_API_KEY = os.environ["E2B_API_KEY"]
46
  HF_TOKEN = os.environ["HF_TOKEN"] #HfFolder.get_token() #
47
  DEFAULT_MAX_TOKENS = 512
 
130
 
131
  with open(save_dir, 'w', encoding='utf-8') as f:
132
  json.dump(init_notebook.data, f, indent=2)
133
+ yield (
134
+ init_notebook.render(),
135
+ init_notebook.render(),
136
+ _messages_to_chat_pairs(message_history),
137
+ message_history,
138
+ save_dir,
139
+ )
140
 
141
  client = OpenAI(
142
  base_url="https://router.huggingface.co/v1",
 
174
  client, model, message_history, sbx,
175
  ):
176
  message_history = messages
177
+
178
+ yield (
179
+ notebook_html,
180
+ notebook_html,
181
+ _messages_to_chat_pairs(message_history),
182
+ message_history,
183
+ TMP_DIR+"jupyter-agent.ipynb",
184
+ )
185
 
186
  with open(save_dir, 'w', encoding='utf-8') as f:
187
  json.dump(notebook_data, f, indent=2)
188
+ yield (
189
+ notebook_html,
190
+ notebook_html,
191
+ _messages_to_chat_pairs(message_history),
192
+ message_history,
193
+ save_dir,
194
+ )
195
 
196
  def clear(msg_state, request: gr.Request):
197
  if request.session_hash in SANDBOXES:
 
203
 
204
 
205
  css = """
206
+ .gradio-container, .contain { height: 100vh !important; }
207
+ .three-col { height: calc(100vh - 20px); }
208
+ .col { display: flex; flex-direction: column; height: 100%; }
209
+ .col .scroll { flex: 1 1 auto; overflow: auto; }
210
+ .controls { margin-top: 8px; }
 
 
 
 
 
 
 
 
211
  """
212
 
213
 
214
  # Create the interface
215
+ with gr.Blocks(css=css) as demo:
216
  msg_state = gr.State(value=[])
217
 
218
+ with gr.Row(elem_classes=["three-col"]):
219
+ # Column 1: Notebook (rendered)
220
+ with gr.Column(scale=1, elem_classes=["col"]):
221
+ notebook_html = gr.HTML(value=JupyterNotebook().render(), label="Notebook", elem_classes=["scroll"])
222
+
223
+ # Column 2: Live HTML Preview (auto-updates with notebook)
224
+ with gr.Column(scale=1, elem_classes=["col"]):
225
+ preview_html = gr.HTML(value=JupyterNotebook().render(), label="Live Preview", elem_classes=["scroll"])
226
+
227
+ # Column 3: Chat interface + controls
228
+ with gr.Column(scale=1, elem_classes=["col"]):
229
+ chatbot = gr.Chatbot(label="Chat", elem_classes=["scroll"])
230
+
231
+ user_input = gr.Textbox(
232
+ value="Solve the Lotka-Volterra equation and plot the results. Do it step by step and explain what you are doing and in the end make a super nice and clean plot.",
233
+ label="Message",
234
+ placeholder="Ask something or give a task...",
235
+ lines=3,
236
+ )
237
+ with gr.Row(elem_classes=["controls"]):
238
+ generate_btn = gr.Button("Send")
239
+ clear_btn = gr.Button("Clear Notebook")
240
+
241
+ with gr.Accordion("Upload files ⬆ | Download notebook⬇", open=False):
242
+ files = gr.File(label="Upload files to use", file_count="multiple")
243
+ file = gr.File(TMP_DIR+"jupyter-agent.ipynb", label="Download Jupyter Notebook")
244
+
245
+ powered_html = gr.HTML("""\
246
+ <p align=\"center\">\
247
+ <img style=\"max-height:100px; max-width:100%; height:auto;\"src=\"https://huggingface.co/spaces/lvwerra/jupyter-agent-2/resolve/main/powered-by.png\" alt=\"Powered by\" />
248
+ </p>""")
249
+
250
+ # Wire interactions: button click and textbox submit both drive the agent
251
  generate_btn.click(
252
  fn=execute_jupyter_agent,
253
  inputs=[user_input, files, msg_state],
254
+ outputs=[notebook_html, preview_html, chatbot, msg_state, file],
255
+ show_progress="hidden",
256
+ )
257
+ user_input.submit(
258
+ fn=execute_jupyter_agent,
259
+ inputs=[user_input, files, msg_state],
260
+ outputs=[notebook_html, preview_html, chatbot, msg_state, file],
261
  show_progress="hidden",
262
  )
263
 
264
+ clear_btn.click(
265
+ fn=clear,
266
+ inputs=[msg_state],
267
+ outputs=[notebook_html, msg_state],
268
+ )
269
 
270
  demo.load(
271
  fn=None,