From 559568b4b1b61d1bfbee35ef545e7754f47d76cc Mon Sep 17 00:00:00 2001 From: LineWalker Date: Wed, 15 Jul 2026 17:57:33 +0800 Subject: [PATCH] feat(linsight): declare available libraries in code-interpreter description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code-interpreter tool description said nothing about which Python packages are available, so the model guessed — reaching for pdfminer.six to read PDFs (a common default) which is NOT installed in the backend env, producing spurious "No module named 'pdfminer'" output (it fell back to fitz, but the noise leaked into the run). Declare the actually-installed libraries (verified in the backend env: pandas, numpy, matplotlib, openpyxl / XlsxWriter, python-docx, Pillow, reportlab, PyMuPDF) and steer PDF reads to `fitz`, away from pdfminer / pdfplumber / PyPDF2. Also tell the model not to `pip install` (shared, offline env). LocalExecutor only — e2b is a different sandbox with a different image, not asserted here. Adds a description-contract regression test. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../tools/code_interpreter/local_executor.py | 9 ++++++++- .../test_code_interpreter_output_path.py | 20 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/backend/bisheng_langchain/gpts/tools/code_interpreter/local_executor.py b/src/backend/bisheng_langchain/gpts/tools/code_interpreter/local_executor.py index 69fc65de5..fe711f9a4 100644 --- a/src/backend/bisheng_langchain/gpts/tools/code_interpreter/local_executor.py +++ b/src/backend/bisheng_langchain/gpts/tools/code_interpreter/local_executor.py @@ -36,7 +36,14 @@ are subfolders of the current working directory. NEVER use an absolute path with leading slash such as `/output/...` or `/scratch/...` — anything written outside the \ current working directory is DISCARDED and will NOT be delivered to the user. \ Do not use things like plot.show() as it will not work; save figures to `output/` \ -instead. print() any output and results so you can capture the output.""" +instead. print() any output and results so you can capture the output. \ +AVAILABLE LIBRARIES: this runs in the backend Python environment; these are ALREADY \ +installed — pandas, numpy, matplotlib (charts), openpyxl / XlsxWriter (Excel), \ +python-docx (Word), Pillow (images), reportlab (generate PDF), and PyMuPDF a.k.a. \ +`fitz` (read/parse PDF). To READ text or tables from a PDF, use `import fitz` \ +(PyMuPDF); do NOT use pdfminer / pdfplumber / PyPDF2 — they are NOT installed. If an \ +import fails, switch to an already-installed library instead of assuming a package \ +exists; do NOT run `pip install` (this is a shared, offline environment).""" class LocalExecutor(BaseExecutor): diff --git a/src/backend/test/linsight/test_code_interpreter_output_path.py b/src/backend/test/linsight/test_code_interpreter_output_path.py index 36fa33604..95b743875 100644 --- a/src/backend/test/linsight/test_code_interpreter_output_path.py +++ b/src/backend/test/linsight/test_code_interpreter_output_path.py @@ -113,3 +113,23 @@ def test_run_failure_path_returns_without_notice(monkeypatch): assert "log" in result # failure path returns early — no file_list, no notice appended assert "file_list" not in result + + +# --------------------------------------------------------------------------- +# LOCAL_DESCRIPTION: available-library guidance +# --------------------------------------------------------------------------- +def test_description_guides_to_installed_pdf_and_data_libs(): + """The tool description names installed libraries and steers PDF reads to + `fitz`, away from pdfminer/pdfplumber/PyPDF2 which the model tends to reach + for but are NOT installed in the backend env. Prevents regressing the + guidance that stops spurious 'No module named pdfminer' output. + """ + d = LocalExecutor(minio={}).description + # PDF read guidance points at the installed lib, not the model's defaults + assert "fitz" in d + assert "pdfminer" in d and "NOT installed" in d + # names an installed PDF generator + core data lib so the model won't guess + assert "reportlab" in d + assert "pandas" in d + # shared, offline env — must not encourage pip install + assert "pip install" in d