sergiopaniego HF Staff commited on
Commit
393e1fa
·
verified ·
1 Parent(s): e7919ba

Upload folder using huggingface_hub

Browse files
openenv_repl.egg-info/PKG-INFO CHANGED
@@ -11,6 +11,7 @@ Requires-Dist: requests>=2.31.0
11
  Requires-Dist: smolagents<2,>=1.22.0
12
  Requires-Dist: huggingface_hub>=0.20.0
13
  Requires-Dist: gradio>=4.0.0
 
14
  Provides-Extra: dev
15
  Requires-Dist: pytest>=9.0.3; extra == "dev"
16
  Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
 
11
  Requires-Dist: smolagents<2,>=1.22.0
12
  Requires-Dist: huggingface_hub>=0.20.0
13
  Requires-Dist: gradio>=4.0.0
14
+ Requires-Dist: pypdf>=4.0.0
15
  Provides-Extra: dev
16
  Requires-Dist: pytest>=9.0.3; extra == "dev"
17
  Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
openenv_repl.egg-info/SOURCES.txt CHANGED
@@ -1,5 +1,14 @@
1
  README.md
 
 
 
 
 
2
  pyproject.toml
 
 
 
 
3
  ./__init__.py
4
  ./client.py
5
  ./local.py
 
1
  README.md
2
+ __init__.py
3
+ client.py
4
+ local.py
5
+ models.py
6
+ prompts.py
7
  pyproject.toml
8
+ recursive_backends.py
9
+ recursive_controller.py
10
+ rubrics.py
11
+ runner.py
12
  ./__init__.py
13
  ./client.py
14
  ./local.py
openenv_repl.egg-info/requires.txt CHANGED
@@ -6,6 +6,7 @@ requests>=2.31.0
6
  smolagents<2,>=1.22.0
7
  huggingface_hub>=0.20.0
8
  gradio>=4.0.0
 
9
 
10
  [dev]
11
  pytest>=9.0.3
 
6
  smolagents<2,>=1.22.0
7
  huggingface_hub>=0.20.0
8
  gradio>=4.0.0
9
+ pypdf>=4.0.0
10
 
11
  [dev]
12
  pytest>=9.0.3
pyproject.toml CHANGED
@@ -26,6 +26,8 @@ dependencies = [
26
  "huggingface_hub>=0.20.0",
27
  # REPL custom Gradio tab on /web
28
  "gradio>=4.0.0",
 
 
29
  ]
30
 
31
  [project.optional-dependencies]
 
26
  "huggingface_hub>=0.20.0",
27
  # REPL custom Gradio tab on /web
28
  "gradio>=4.0.0",
29
+ # Document upload support in the Gradio tab (server-side only, not in the sandbox)
30
+ "pypdf>=4.0.0",
31
  ]
32
 
33
  [project.optional-dependencies]
server/gradio_ui.py CHANGED
@@ -8,12 +8,19 @@
8
 
9
  from __future__ import annotations
10
 
 
11
  import json
 
12
  from typing import Any, Dict, List, Optional
13
 
14
  import gradio as gr
15
  from openenv.core.env_server.types import EnvironmentMetadata
16
 
 
 
 
 
 
17
 
18
  # Pre-canned demos for the "Load example" dropdown. Each entry is
19
  # (label, context, task_prompt, code) and showcases one of the three
@@ -104,6 +111,33 @@ Pass **Expected answer** at Reset to enable rubric-based scoring: the observatio
104
  """
105
 
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  def _code_block(title: str, content: str) -> str:
108
  if not content:
109
  return ""
@@ -229,11 +263,26 @@ def build_repl_gradio_app(
229
  ctx, task, code, expected = _EXAMPLES[label]
230
  return ctx, task, code, expected
231
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  with gr.Blocks(title=f"{title} - REPL") as blocks:
233
  gr.Markdown(
234
  "# REPL Control Panel\n\n"
235
- "Recursive Language Model REPL. Pick a demo from **💡 Load example** below, "
236
- "paste your **Hugging Face Token**, click **🔁 Reset episode**, then **▶ Run**.\n\n"
 
237
  "*Injected helpers: `context`, `llm_query`, `llm_query_batched`, "
238
  "`rlm_query`, `rlm_query_batched`, `FINAL(...)`, `FINAL_VAR(...)`.*"
239
  )
@@ -247,6 +296,11 @@ def build_repl_gradio_app(
247
  value=None,
248
  info="Pick a pre-canned demo to fill Context, Task Prompt, and Python Code.",
249
  )
 
 
 
 
 
250
  context = gr.Textbox(
251
  label="Context",
252
  placeholder="Problem context or source text...",
@@ -338,5 +392,10 @@ def build_repl_gradio_app(
338
  inputs=[example_dropdown],
339
  outputs=[context, task_prompt, code, expected_answer],
340
  )
 
 
 
 
 
341
 
342
  return blocks
 
8
 
9
  from __future__ import annotations
10
 
11
+ import io
12
  import json
13
+ from pathlib import Path
14
  from typing import Any, Dict, List, Optional
15
 
16
  import gradio as gr
17
  from openenv.core.env_server.types import EnvironmentMetadata
18
 
19
+ try:
20
+ import pypdf
21
+ except ImportError: # pragma: no cover - optional dep
22
+ pypdf = None # type: ignore[assignment]
23
+
24
 
25
  # Pre-canned demos for the "Load example" dropdown. Each entry is
26
  # (label, context, task_prompt, code) and showcases one of the three
 
111
  """
112
 
113
 
114
+ def _extract_text_from_upload(file_path: str) -> str:
115
+ """Read a .txt or .pdf upload from disk and return its text content.
116
+
117
+ Runs in the Gradio server process (outside the smolagents sandbox),
118
+ so it can use `pypdf` and the filesystem without triggering the
119
+ REPL's import restrictions.
120
+ """
121
+ path = Path(file_path)
122
+ suffix = path.suffix.lower()
123
+ if suffix == ".txt":
124
+ return path.read_text(encoding="utf-8", errors="replace")
125
+ if suffix == ".pdf":
126
+ if pypdf is None:
127
+ return "[pypdf is not installed in this deployment; cannot parse PDFs.]"
128
+ with path.open("rb") as fh:
129
+ reader = pypdf.PdfReader(io.BytesIO(fh.read()))
130
+ pages = []
131
+ for page in reader.pages:
132
+ try:
133
+ pages.append(page.extract_text() or "")
134
+ except Exception as exc: # pypdf can raise on malformed PDFs
135
+ pages.append(f"[page extraction failed: {exc}]")
136
+ text = "\n\n".join(pages).strip()
137
+ return text or "[No extractable text — PDF may be image-only.]"
138
+ return f"[Unsupported file type: {suffix}. Use .txt or .pdf.]"
139
+
140
+
141
  def _code_block(title: str, content: str) -> str:
142
  if not content:
143
  return ""
 
263
  ctx, task, code, expected = _EXAMPLES[label]
264
  return ctx, task, code, expected
265
 
266
+ def load_uploaded_document(file_obj):
267
+ if file_obj is None:
268
+ return gr.update(), gr.update()
269
+ file_path = (
270
+ file_obj if isinstance(file_obj, str) else getattr(file_obj, "name", None)
271
+ )
272
+ if not file_path:
273
+ return gr.update(), "Upload error: could not read file path."
274
+ try:
275
+ text = _extract_text_from_upload(file_path)
276
+ except Exception as exc:
277
+ return gr.update(), f"Upload error: {exc}"
278
+ return text, f"Loaded {Path(file_path).name} ({len(text)} chars) into Context."
279
+
280
  with gr.Blocks(title=f"{title} - REPL") as blocks:
281
  gr.Markdown(
282
  "# REPL Control Panel\n\n"
283
+ "Recursive Language Model REPL. Pick a demo from **💡 Load example**, or drop "
284
+ "your own **text file / PDF**, paste your **Hugging Face Token**, "
285
+ "click **🔁 Reset episode**, then **▶ Run**.\n\n"
286
  "*Injected helpers: `context`, `llm_query`, `llm_query_batched`, "
287
  "`rlm_query`, `rlm_query_batched`, `FINAL(...)`, `FINAL_VAR(...)`.*"
288
  )
 
296
  value=None,
297
  info="Pick a pre-canned demo to fill Context, Task Prompt, and Python Code.",
298
  )
299
+ upload = gr.File(
300
+ label="📎 Drop a text file or PDF here",
301
+ file_types=[".txt", ".pdf"],
302
+ type="filepath",
303
+ )
304
  context = gr.Textbox(
305
  label="Context",
306
  placeholder="Problem context or source text...",
 
392
  inputs=[example_dropdown],
393
  outputs=[context, task_prompt, code, expected_answer],
394
  )
395
+ upload.change(
396
+ fn=load_uploaded_document,
397
+ inputs=[upload],
398
+ outputs=[context, status],
399
+ )
400
 
401
  return blocks
uv.lock CHANGED
@@ -1608,6 +1608,7 @@ dependencies = [
1608
  { name = "huggingface-hub" },
1609
  { name = "openenv-core", extra = ["core"] },
1610
  { name = "pydantic" },
 
1611
  { name = "requests" },
1612
  { name = "smolagents" },
1613
  { name = "uvicorn" },
@@ -1626,6 +1627,7 @@ requires-dist = [
1626
  { name = "huggingface-hub", specifier = ">=0.20.0" },
1627
  { name = "openenv-core", extras = ["core"], specifier = ">=0.2.3" },
1628
  { name = "pydantic", specifier = ">=2.0.0" },
 
1629
  { name = "pytest", marker = "extra == 'dev'", specifier = ">=9.0.3" },
1630
  { name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=4.0.0" },
1631
  { name = "requests", specifier = ">=2.31.0" },
@@ -2218,6 +2220,18 @@ crypto = [
2218
  { name = "cryptography" },
2219
  ]
2220
 
 
 
 
 
 
 
 
 
 
 
 
 
2221
  [[package]]
2222
  name = "pyperclip"
2223
  version = "1.11.0"
 
1608
  { name = "huggingface-hub" },
1609
  { name = "openenv-core", extra = ["core"] },
1610
  { name = "pydantic" },
1611
+ { name = "pypdf" },
1612
  { name = "requests" },
1613
  { name = "smolagents" },
1614
  { name = "uvicorn" },
 
1627
  { name = "huggingface-hub", specifier = ">=0.20.0" },
1628
  { name = "openenv-core", extras = ["core"], specifier = ">=0.2.3" },
1629
  { name = "pydantic", specifier = ">=2.0.0" },
1630
+ { name = "pypdf", specifier = ">=4.0.0" },
1631
  { name = "pytest", marker = "extra == 'dev'", specifier = ">=9.0.3" },
1632
  { name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=4.0.0" },
1633
  { name = "requests", specifier = ">=2.31.0" },
 
2220
  { name = "cryptography" },
2221
  ]
2222
 
2223
+ [[package]]
2224
+ name = "pypdf"
2225
+ version = "6.10.2"
2226
+ source = { registry = "https://pypi.org/simple" }
2227
+ dependencies = [
2228
+ { name = "typing-extensions", marker = "python_full_version < '3.11'" },
2229
+ ]
2230
+ sdist = { url = "https://files.pythonhosted.org/packages/7b/3f/9f2167401c2e94833ca3b69535bad89e533b5de75fefe4197a2c224baec2/pypdf-6.10.2.tar.gz", hash = "sha256:7d09ce108eff6bf67465d461b6ef352dcb8d84f7a91befc02f904455c6eea11d", size = 5315679, upload-time = "2026-04-15T16:37:36.978Z" }
2231
+ wheels = [
2232
+ { url = "https://files.pythonhosted.org/packages/0c/d6/1d5c60cc17bbdf37c1552d9c03862fc6d32c5836732a0415b2d637edc2d0/pypdf-6.10.2-py3-none-any.whl", hash = "sha256:aa53be9826655b51c96741e5d7983ca224d898ac0a77896e64636810517624aa", size = 336308, upload-time = "2026-04-15T16:37:34.851Z" },
2233
+ ]
2234
+
2235
  [[package]]
2236
  name = "pyperclip"
2237
  version = "1.11.0"