From 446fc7e2fdd0b34636c7bcb9035178444805485a Mon Sep 17 00:00:00 2001 From: Johnny-zbb <54133977+Johnny-zbb@users.noreply.github.com> Date: Sat, 16 May 2026 16:18:36 +0800 Subject: [PATCH 1/3] docs(integrations): add LlamaIndex integration guide --- docs/guide/integrations/index.md | 2 +- docs/guide/integrations/llamaindex.md | 258 ++++++++++++++++++++++ docs/zh/guide/integrations/index.md | 2 +- docs/zh/guide/integrations/llamaindex.md | 262 +++++++++++++++++++++++ 4 files changed, 522 insertions(+), 2 deletions(-) create mode 100644 docs/guide/integrations/llamaindex.md create mode 100644 docs/zh/guide/integrations/llamaindex.md diff --git a/docs/guide/integrations/index.md b/docs/guide/integrations/index.md index 8b811b29c..484735768 100644 --- a/docs/guide/integrations/index.md +++ b/docs/guide/integrations/index.md @@ -47,4 +47,4 @@ lang: en-US | Title | Author | Date | Tags | | --- | --- | --- | --- | -| _Add your article here_ | - | - | - | +| LlamaIndex Integration Guide | Johnny-zbb | 2026-05-16 | integration, llamaindex | diff --git a/docs/guide/integrations/llamaindex.md b/docs/guide/integrations/llamaindex.md new file mode 100644 index 000000000..78a0b35bc --- /dev/null +++ b/docs/guide/integrations/llamaindex.md @@ -0,0 +1,258 @@ +--- +title: LlamaIndex Integration Guide +author: Johnny-zbb +date: 2026-05-16 +tags: + - integration + - llamaindex +lang: en-US +--- + +# LlamaIndex Integration Guide + +## Integration Target and Version + +[LlamaIndex](https://www.llamaindex.ai/) is a data framework for building LLM applications with custom knowledge bases. This guide covers integrating LlamaIndex with Cube Sandbox as a secure, isolated code execution environment for RAG (Retrieval-Augmented Generation) workflows. + +- **Tested LlamaIndex versions**: `>= 0.10.0` +- **Tested Python versions**: `3.9+` +- **Integration type**: Code execution tool (Tool) + +## Prerequisites + +- Cube Sandbox deployment (see [Quick Start](https://github.com/TencentCloud/CubeSandbox)) +- Python `3.9+` with `pip` +- LlamaIndex installed: `pip install llama-index` +- Environment variables configured: + +```bash +export CUBE_API_URL=http://:3000 +export CUBE_TEMPLATE_ID= +export CUBE_PROXY_NODE_IP= # for remote access +``` + +## Integration Steps + +### 1. Install dependencies + +```bash +pip install llama-index llama-index-agent-openai +``` + +### 2. Create a Cube Sandbox tool for LlamaIndex + +The key insight: replacing `SimpleDirectoryReader` or local Python execution with Cube Sandbox gives you **MicroVM-level isolation** — no shared host process, no interference between agents. + +```python +# tools/cube_tool.py +import json +from llama_index.core.tools import FunctionTool +from cubesandbox import Sandbox, Config + + +def create_cube_tool( + template_id: str, + api_url: str = "http://127.0.0.1:3000", + proxy_node_ip: str = "", + timeout: int = 60, +) -> FunctionTool: + """ + Create a LlamaIndex FunctionTool backed by a Cube Sandbox. + + Args: + template_id: Cube template ID (e.g. python:3.12-slim) + api_url: CubeAPI address + proxy_node_ip: CubeProxy node IP for remote access + timeout: max execution time in seconds + """ + + def _run_code(code: str) -> str: + cfg = Config( + api_url=api_url, + template_id=template_id, + proxy_node_ip=proxy_node_ip, + ) + with Sandbox.create(config=cfg) as sb: + result = sb.run_code(code, timeout=timeout) + if result.error: + return f"Error: {result.error.name}: {result.error.value}" + return result.text or "" + + return FunctionTool.from_defaults( + fn=_run_code, + name="cube_sandbox", + description=( + "Executes Python code inside an isolated Cube Sandbox MicroVM. " + "Use this for untrusted code, RAG data processing, or any operation " + "that needs strong isolation. " + "Input: a single Python code string to execute. " + "Output: the result of the last expression or stdout/stderr." + ), + ) +``` + +### 3. Use with a LlamaIndex agent + +```python +# main.py +from llama_index.core.agent import ReActAgent +from llama_index.llms.openai import OpenAI +from tools.cube_tool import create_cube_tool + +llm = OpenAI(model="gpt-4o") + +# Register Cube tool as a code execution backend +agent = ReActAgent.from_tools( + tools=[create_cube_tool( + template_id="python:3.12-slim", + api_url="http://localhost:3000", + )], + llm=llm, + verbose=True, +) + +response = agent.chat( + "Download the Wikipedia page about RAG, " + "parse it with BeautifulSoup, and compute word frequency stats." +) +print(response) +``` + +## Key Code Snippets + +### Before (local execution, no isolation) + +```python +# Dangerous: code runs directly on the host +exec(""" +import requests +from bs4 import BeautifulSoup + +url = "https://en.wikipedia.org/wiki/Retrieval-Augmented-Generation" +html = requests.get(url).text +soup = BeautifulSoup(html, "html.parser") +# ... full host access, no sandboxing +""") +``` + +### After (Cube Sandbox, MicroVM isolation) + +```python +# Same logic, but inside an isolated MicroVM +from cubesandbox import Sandbox, Config + +cfg = Config( + api_url="http://localhost:3000", + template_id="python:3.12-slim", +) +with Sandbox.create(config=cfg) as sb: + result = sb.run_code(""" +import urllib.request +from html.parser import HTMLParser + +class WordFreq(HTMLParser): + def __init__(self): + super().__init__() + self.words = [] + self.skip = {'the','a','an','is','are','was','were','in','on','at','to','of','for'} + def handle_data(self, data): + for w in data.lower().split(): + w = w.strip('.,!?;:\"()[]{}') + if w and w not in self.skip and len(w) > 3: + self.words.append(w) + +url = "https://en.wikipedia.org/wiki/Retrieval-Augmented-Generation" +req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'}) +html = urllib.request.urlopen(req).read().decode() +p = WordFreq(); p.feed(html) +from collections import Counter +print(Counter(p.words).most_common(10)) + """, timeout=30) + print(result.text) +``` + +### Diff summary + +```diff +- exec("""...""") # runs on host, no isolation ++ with Sandbox.create(config=cfg) as sb: ++ sb.run_code("""...") # runs in MicroVM, fully isolated +``` + +**The refactor is minimal**: wrap your existing code in `sb.run_code("""...")`, and you're done. + +## Going Further + +### Network isolation for untrusted data sources + +LlamaIndex often fetches data from external URLs. Cube Sandbox supports network policies: + +```python +# Deny all outbound — no data exfiltration risk +with Sandbox.create( + metadata={"network-policy": "deny-all"} +) as sb: + # can still read local files mounted via hostdir-mount + result = sb.run_code("open('/mnt/data/input.txt').read()") + +# Allow specific IPs only +rules = json.dumps({"allow": ["151.101.0.0/16"]}) # GitHub IPs +with Sandbox.create( + metadata={"network-policy": "custom", "network-rules": rules} +) as sb: + result = sb.run_code(""" +import urllib.request +urllib.request.urlopen('https://api.github.com').read() + """) +``` + +### Persistent sandbox for multi-turn RAG + +Keep a sandbox alive across multiple `run_code` calls for stateful RAG pipelines: + +```python +sb = Sandbox.create(config=cfg) + +# Build index in sandbox +sb.run_code(""" +from llama_index.core import SimpleDirectoryReader +documents = SimpleDirectoryReader('./data').load_data() +print(f"Loaded {len(documents)} documents") +""") + +# Query in same sandbox (variables persist) +sb.run_code(""" +from llama_index.core import VectorStoreIndex +index = VectorStoreIndex.from_documents(documents) +print("Index built") +""") + +sb.kill() # clean up +``` + +### Pause & resume for cost control + +```python +sb = Sandbox.create() + +# Pause when idle — memory snapshot, no billing +sb.pause() # waits for state=paused + +# Resume when needed +sb2 = Sandbox.connect(sb.sandbox_id) +result = sb2.run_code("print('resumed')") +``` + +## Caveats + +- **Cold start latency**: Cube Sandbox spawns a MicroVM on first `Sandbox.create()`, which takes ~1–2s. For latency-sensitive interactive use, consider keeping a sandbox warm via `pause()`/`connect()` instead of repeatedly creating new ones. +- **Python SDK only for now**: The Cube Sandbox Python SDK is the recommended integration path for LlamaIndex. Other SDKs (Go, etc.) are not yet covered in this guide. +- **No kernel context persistence yet**: Variables do not persist across separate `Sandbox.create()` calls. Use a single sandbox instance for stateful pipelines, or mount a host directory for file-based state sharing. +- **Network policy domain limitation**: Custom `allow` rules only support IP ranges/CIDRs, not domain names. Plan accordingly for external API access. + +## References + +- [Cube Sandbox Python SDK](https://github.com/TencentCloud/CubeSandbox/tree/main/sdk/python) +- [LlamaIndex Documentation](https://docs.llamaindex.ai/) +- [Cube Sandbox GitHub](https://github.com/TencentCloud/CubeSandbox) +- [Cube Sandbox Quick Start Guide](https://github.com/TencentCloud/CubeSandbox/blob/main/README.md) diff --git a/docs/zh/guide/integrations/index.md b/docs/zh/guide/integrations/index.md index 0fc983d6f..5d62a51b1 100644 --- a/docs/zh/guide/integrations/index.md +++ b/docs/zh/guide/integrations/index.md @@ -47,4 +47,4 @@ lang: zh-CN | 标题 | 作者 | 日期 | 标签 | | --- | --- | --- | --- | -| _在这里补充你的文章_ | - | - | - | +| LlamaIndex 集成指南 | Johnny-zbb | 2026-05-16 | integration, llamaindex | diff --git a/docs/zh/guide/integrations/llamaindex.md b/docs/zh/guide/integrations/llamaindex.md new file mode 100644 index 000000000..773b0c2ae --- /dev/null +++ b/docs/zh/guide/integrations/llamaindex.md @@ -0,0 +1,262 @@ +--- +title: LlamaIndex 集成指南 +author: Johnny-zbb +date: 2026-05-16 +tags: + - integration + - llamaindex +lang: zh-CN +--- + +# LlamaIndex 集成指南 + +## 集成对象与版本 + +[LlamaIndex](https://www.llamaindex.ai/) 是一个数据框架,用于基于自定义知识库构建 LLM 应用。本指南介绍如何将 LlamaIndex 与 Cube Sandbox 集成 — 以安全隔离的代码执行环境驱动 RAG(检索增强生成)工作流。 + +- **已验证 LlamaIndex 版本**:`>= 0.10.0` +- **已验证 Python 版本**:`3.9+` +- **集成类型**:代码执行工具(Tool) + +## 前置条件 + +- Cube Sandbox 已部署(参考 [快速入门](https://github.com/TencentCloud/CubeSandbox)) +- Python `3.9+`,已装 `pip` +- 安装依赖: + +```bash +pip install llama-index llama-index-agent-openai +``` + +- 配置环境变量: + +```bash +export CUBE_API_URL=http://:3000 +export CUBE_TEMPLATE_ID= +export CUBE_PROXY_NODE_IP= # 远程访问时需要 +``` + +## 接入步骤 + +### 1. 安装依赖 + +```bash +pip install llama-index llama-index-agent-openai +``` + +### 2. 为 LlamaIndex 创建 Cube Sandbox 工具 + +核心思路:用 Cube Sandbox 替换 `SimpleDirectoryReader` 或本地 Python 执行,可以获得 **MicroVM 级隔离** — 不共享宿主机进程,Agent 之间互不干扰。 + +```python +# tools/cube_tool.py +import json +from llama_index.core.tools import FunctionTool +from cubesandbox import Sandbox, Config + + +def create_cube_tool( + template_id: str, + api_url: str = "http://127.0.0.1:3000", + proxy_node_ip: str = "", + timeout: int = 60, +) -> FunctionTool: + """ + 创建一个由 Cube Sandbox 驱动的 LlamaIndex FunctionTool。 + + Args: + template_id: Cube 模板 ID(如 python:3.12-slim) + api_url: CubeAPI 地址 + proxy_node_ip: CubeProxy 节点 IP(远程访问时填写) + timeout: 最大执行时间(秒) + """ + + def _run_code(code: str) -> str: + cfg = Config( + api_url=api_url, + template_id=template_id, + proxy_node_ip=proxy_node_ip, + ) + with Sandbox.create(config=cfg) as sb: + result = sb.run_code(code, timeout=timeout) + if result.error: + return f"Error: {result.error.name}: {result.error.value}" + return result.text or "" + + return FunctionTool.from_defaults( + fn=_run_code, + name="cube_sandbox", + description=( + "在隔离的 Cube Sandbox MicroVM 中执行 Python 代码。" + "适用于运行不受信任的代码、RAG 数据处理,或任何需要强隔离的操作。" + "输入:待执行的单个 Python 代码字符串。" + "输出:最后一个表达式的结果或标准输出/标准错误。" + ), + ) +``` + +### 3. 与 LlamaIndex Agent 配合使用 + +```python +# main.py +from llama_index.core.agent import ReActAgent +from llama_index.llms.openai import OpenAI +from tools.cube_tool import create_cube_tool + +llm = OpenAI(model="gpt-4o") + +# 注册 Cube 工具作为代码执行后端 +agent = ReActAgent.from_tools( + tools=[create_cube_tool( + template_id="python:3.12-slim", + api_url="http://localhost:3000", + )], + llm=llm, + verbose=True, +) + +response = agent.chat( + "下载维基百科上关于 RAG 的词条," + "用 BeautifulSoup 解析它,然后统计词频。" +) +print(response) +``` + +## 关键代码片段 + +### 原始做法(本地执行,无隔离) + +```python +# 危险:代码直接在宿主机运行 +exec(""" +import requests +from bs4 import BeautifulSoup + +url = "https://en.wikipedia.org/wiki/Retrieval-Augmented-Generation" +html = requests.get(url).text +soup = BeautifulSoup(html, "html.parser") +# ... 完全的宿主机访问权限,无任何沙箱保护 +""") +``` + +### 改造后(Cube Sandbox,MicroVM 隔离) + +```python +# 相同逻辑,但在隔离的 MicroVM 中执行 +from cubesandbox import Sandbox, Config + +cfg = Config( + api_url="http://localhost:3000", + template_id="python:3.12-slim", +) +with Sandbox.create(config=cfg) as sb: + result = sb.run_code(""" +import urllib.request +from html.parser import HTMLParser + +class WordFreq(HTMLParser): + def __init__(self): + super().__init__() + self.words = [] + self.skip = {'the','a','an','is','are','was','were','in','on','at','to','of','for'} + def handle_data(self, data): + for w in data.lower().split(): + w = w.strip('.,!?;:\"()[]{}') + if w and w not in self.skip and len(w) > 3: + self.words.append(w) + +url = "https://en.wikipedia.org/wiki/Retrieval-Augmented-Generation" +req = urllib.request.Request(url, headers={'User-Agent': 'Mozilla/5.0'}) +html = urllib.request.urlopen(req).read().decode() +p = WordFreq(); p.feed(html) +from collections import Counter +print(Counter(p.words).most_common(10)) + """, timeout=30) + print(result.text) +``` + +### 改动对比 + +```diff +- exec("""...""") # 直接在宿主机运行,无隔离 ++ with Sandbox.create(config=cfg) as sb: ++ sb.run_code("""...") # 在 MicroVM 中运行,完全隔离 +``` + +**改造幅度极小**:只需把现有代码包裹在 `sb.run_code("""...")` 中,即可完成迁移。 + +## 进阶配置 + +### 网络隔离(处理不可信数据源) + +LlamaIndex 常需从外部 URL 获取数据,Cube Sandbox 支持细粒度网络策略: + +```python +# 完全禁止出站流量 — 避免数据泄露风险 +with Sandbox.create( + metadata={"network-policy": "deny-all"} +) as sb: + # 只能读取通过 hostdir-mount 挂载的本地文件 + result = sb.run_code("open('/mnt/data/input.txt').read()") + +# 仅允许特定 IP 范围 +rules = json.dumps({"allow": ["151.101.0.0/16"]}) # GitHub IP 段 +with Sandbox.create( + metadata={"network-policy": "custom", "network-rules": rules} +) as sb: + result = sb.run_code(""" +import urllib.request +urllib.request.urlopen('https://api.github.com').read() + """) +``` + +### 多轮 RAG 的持久化沙箱 + +在多次 `run_code` 调用间保持同一个沙箱,实现有状态的 RAG 流水线: + +```python +sb = Sandbox.create(config=cfg) + +# 在沙箱中构建索引 +sb.run_code(""" +from llama_index.core import SimpleDirectoryReader +documents = SimpleDirectoryReader('./data').load_data() +print(f"加载了 {len(documents)} 个文档") +""") + +# 在同一沙箱中查询(变量持久化) +sb.run_code(""" +from llama_index.core import VectorStoreIndex +index = VectorStoreIndex.from_documents(documents) +print("索引构建完成") +""") + +sb.kill() # 清理 +``` + +### 暂停与恢复控制成本 + +```python +sb = Sandbox.create() + +# 空闲时暂停 — 内存快照,不计费 +sb.pause() # 等待状态变为 paused + +# 需要时恢复 +sb2 = Sandbox.connect(sb.sandbox_id) +result = sb2.run_code("print('已恢复')") +``` + +## 注意事项 + +- **冷启动延迟**:Cube Sandbox 在首次 `Sandbox.create()` 时会启动一个 MicroVM,耗时约 1–2 秒。对延迟敏感的交互场景,建议通过 `pause()`/`connect()` 保持沙箱热状态,避免反复创建新实例。 +- **目前仅支持 Python SDK**:Cube Sandbox Python SDK 是与 LlamaIndex 集成的推荐路径。其他语言 SDK(Go 等)暂未纳入本指南范围。 +- **暂不支持内核上下文持久化**:不同 `Sandbox.create()` 调用之间变量不共享。如需有状态流水线,请使用同一沙箱实例;或通过 hostdir-mount 以文件形式共享状态。 +- **网络策略仅支持 IP/CIDR**:自定义 `allow` 规则暂不支持域名。请提前规划外部 API 的 IP 范围。 + +## 参考资料 + +- [Cube Sandbox Python SDK](https://github.com/TencentCloud/CubeSandbox/tree/main/sdk/python) +- [LlamaIndex 官方文档](https://docs.llamaindex.ai/) +- [Cube Sandbox GitHub 仓库](https://github.com/TencentCloud/CubeSandbox) +- [Cube Sandbox 快速入门](https://github.com/TencentCloud/CubeSandbox/blob/main/README.md) From 0cf5d1efce9af9a01abeceeb80efa9dc62427984 Mon Sep 17 00:00:00 2001 From: Johnny-zbb <54133977+Johnny-zbb@users.noreply.github.com> Date: Sat, 16 May 2026 18:23:48 +0800 Subject: [PATCH 2/3] docs(integrations): fix LlamaIndex guide based on PR review feedback - Replace invalid template_id='python:3.12-slim' with placeholder - Add template creation instructions to Prerequisites section - Use SDK native network parameter for network isolation (network={"allow_out": [...]}) - Add config=cfg to Sandbox.create() calls in network examples - Remove unused 'import json' statement - Fix metadata={} usage to SDK-native parameters --- docs/guide/integrations/llamaindex.md | 44 +++++++++++++++++------- docs/zh/guide/integrations/llamaindex.md | 44 +++++++++++++++++------- 2 files changed, 64 insertions(+), 24 deletions(-) diff --git a/docs/guide/integrations/llamaindex.md b/docs/guide/integrations/llamaindex.md index 78a0b35bc..1c034a791 100644 --- a/docs/guide/integrations/llamaindex.md +++ b/docs/guide/integrations/llamaindex.md @@ -23,11 +23,26 @@ lang: en-US - Cube Sandbox deployment (see [Quick Start](https://github.com/TencentCloud/CubeSandbox)) - Python `3.9+` with `pip` - LlamaIndex installed: `pip install llama-index` +- A Cube Sandbox template. If you don't have one: + 1. Build from base image with `envd` support, e.g.: + + ```dockerfile + FROM cubesandbox-base:latest + # Or: FROM ghcr.io/tencentcloud/cubesandbox-base:2026.16 + ``` + + 2. Create a template via CLI: + ```bash + cubemastercli tpl create-from-image --image + # Output includes: template_id="tpl-xxxxxxxxxxxx" + ``` + 3. Use the returned `template_id` (format: `tpl-`) in your code. + - Environment variables configured: ```bash export CUBE_API_URL=http://:3000 -export CUBE_TEMPLATE_ID= +export CUBE_TEMPLATE_ID= # e.g. tpl-748094d2f2374b0a8a37e6ec export CUBE_PROXY_NODE_IP= # for remote access ``` @@ -45,7 +60,6 @@ The key insight: replacing `SimpleDirectoryReader` or local Python execution wit ```python # tools/cube_tool.py -import json from llama_index.core.tools import FunctionTool from cubesandbox import Sandbox, Config @@ -60,7 +74,7 @@ def create_cube_tool( Create a LlamaIndex FunctionTool backed by a Cube Sandbox. Args: - template_id: Cube template ID (e.g. python:3.12-slim) + template_id: Cube template ID (e.g. tpl-748094d2f2374b0a8a37e6ec) api_url: CubeAPI address proxy_node_ip: CubeProxy node IP for remote access timeout: max execution time in seconds @@ -104,7 +118,7 @@ llm = OpenAI(model="gpt-4o") # Register Cube tool as a code execution backend agent = ReActAgent.from_tools( tools=[create_cube_tool( - template_id="python:3.12-slim", + template_id="", # e.g. tpl-748094d2f2374b0a8a37e6ec api_url="http://localhost:3000", )], llm=llm, @@ -143,7 +157,7 @@ from cubesandbox import Sandbox, Config cfg = Config( api_url="http://localhost:3000", - template_id="python:3.12-slim", + template_id="", # e.g. tpl-748094d2f2374b0a8a37e6ec ) with Sandbox.create(config=cfg) as sb: result = sb.run_code(""" @@ -185,20 +199,26 @@ print(Counter(p.words).most_common(10)) ### Network isolation for untrusted data sources -LlamaIndex often fetches data from external URLs. Cube Sandbox supports network policies: +LlamaIndex often fetches data from external URLs. Cube Sandbox supports network policies via the SDK's native `network` parameter: ```python +from cubesandbox import Sandbox, Config + +cfg = Config( + api_url="http://localhost:3000", + template_id="", +) + # Deny all outbound — no data exfiltration risk -with Sandbox.create( - metadata={"network-policy": "deny-all"} -) as sb: +with Sandbox.create(config=cfg, allow_internet_access=False) as sb: # can still read local files mounted via hostdir-mount result = sb.run_code("open('/mnt/data/input.txt').read()") -# Allow specific IPs only -rules = json.dumps({"allow": ["151.101.0.0/16"]}) # GitHub IPs +# Allow specific IP ranges only (CIDR notation) with Sandbox.create( - metadata={"network-policy": "custom", "network-rules": rules} + config=cfg, + allow_internet_access=False, + network={"allow_out": ["151.101.0.0/16"]}, # GitHub IP range ) as sb: result = sb.run_code(""" import urllib.request diff --git a/docs/zh/guide/integrations/llamaindex.md b/docs/zh/guide/integrations/llamaindex.md index 773b0c2ae..1c9f14173 100644 --- a/docs/zh/guide/integrations/llamaindex.md +++ b/docs/zh/guide/integrations/llamaindex.md @@ -28,11 +28,26 @@ lang: zh-CN pip install llama-index llama-index-agent-openai ``` +- 准备 Cube Sandbox 模板(如果没有): + 1. 基于 Cube Sandbox 基础镜像构建(包含 `envd` 支持),例如: + + ```dockerfile + FROM cubesandbox-base:latest + # 或: FROM ghcr.io/tencentcloud/cubesandbox-base:2026.16 + ``` + + 2. 通过 CLI 创建模板: + ```bash + cubemastercli tpl create-from-image --image + # 输出包含: template_id="tpl-xxxxxxxxxxxx" + ``` + 3. 使用返回的 `template_id`(格式:`tpl-`)。 + - 配置环境变量: ```bash export CUBE_API_URL=http://:3000 -export CUBE_TEMPLATE_ID= +export CUBE_TEMPLATE_ID= # 例如 tpl-748094d2f2374b0a8a37e6ec export CUBE_PROXY_NODE_IP= # 远程访问时需要 ``` @@ -50,7 +65,6 @@ pip install llama-index llama-index-agent-openai ```python # tools/cube_tool.py -import json from llama_index.core.tools import FunctionTool from cubesandbox import Sandbox, Config @@ -65,7 +79,7 @@ def create_cube_tool( 创建一个由 Cube Sandbox 驱动的 LlamaIndex FunctionTool。 Args: - template_id: Cube 模板 ID(如 python:3.12-slim) + template_id: Cube 模板 ID(如 tpl-748094d2f2374b0a8a37e6ec) api_url: CubeAPI 地址 proxy_node_ip: CubeProxy 节点 IP(远程访问时填写) timeout: 最大执行时间(秒) @@ -108,7 +122,7 @@ llm = OpenAI(model="gpt-4o") # 注册 Cube 工具作为代码执行后端 agent = ReActAgent.from_tools( tools=[create_cube_tool( - template_id="python:3.12-slim", + template_id="", # 例如 tpl-748094d2f2374b0a8a37e6ec api_url="http://localhost:3000", )], llm=llm, @@ -147,7 +161,7 @@ from cubesandbox import Sandbox, Config cfg = Config( api_url="http://localhost:3000", - template_id="python:3.12-slim", + template_id="", # 例如 tpl-748094d2f2374b0a8a37e6ec ) with Sandbox.create(config=cfg) as sb: result = sb.run_code(""" @@ -189,20 +203,26 @@ print(Counter(p.words).most_common(10)) ### 网络隔离(处理不可信数据源) -LlamaIndex 常需从外部 URL 获取数据,Cube Sandbox 支持细粒度网络策略: +LlamaIndex 常需从外部 URL 获取数据,Cube Sandbox 支持通过 SDK 原生的 `network` 参数实现细粒度网络策略: ```python +from cubesandbox import Sandbox, Config + +cfg = Config( + api_url="http://localhost:3000", + template_id="", +) + # 完全禁止出站流量 — 避免数据泄露风险 -with Sandbox.create( - metadata={"network-policy": "deny-all"} -) as sb: +with Sandbox.create(config=cfg, allow_internet_access=False) as sb: # 只能读取通过 hostdir-mount 挂载的本地文件 result = sb.run_code("open('/mnt/data/input.txt').read()") -# 仅允许特定 IP 范围 -rules = json.dumps({"allow": ["151.101.0.0/16"]}) # GitHub IP 段 +# 仅允许特定 IP 范围(CIDR 表示法) with Sandbox.create( - metadata={"network-policy": "custom", "network-rules": rules} + config=cfg, + allow_internet_access=False, + network={"allow_out": ["151.101.0.0/16"]}, # GitHub IP 段 ) as sb: result = sb.run_code(""" import urllib.request From 41e305bb8f7b1ee18dfff370a82a5d6bc26871b2 Mon Sep 17 00:00:00 2001 From: Johnny-zbb <54133977+Johnny-zbb@users.noreply.github.com> Date: Sat, 16 May 2026 19:36:27 +0800 Subject: [PATCH 3/3] feat(examples): add LlamaIndex integration example - Complete Python example for LlamaIndex + CubeSandbox integration - Demonstrates RAG workflow with secure code execution - Includes network isolation examples - Bilingual README (English + Chinese) - Environment configuration templates --- examples/llamaindex-integration/.env.example | 31 ++ examples/llamaindex-integration/README.md | 107 +++++++ examples/llamaindex-integration/README_zh.md | 165 ++++++++++ .../llamaindex_integration.py | 293 ++++++++++++++++++ .../llamaindex-integration/requirements.txt | 12 + 5 files changed, 608 insertions(+) create mode 100644 examples/llamaindex-integration/.env.example create mode 100644 examples/llamaindex-integration/README.md create mode 100644 examples/llamaindex-integration/README_zh.md create mode 100644 examples/llamaindex-integration/llamaindex_integration.py create mode 100644 examples/llamaindex-integration/requirements.txt diff --git a/examples/llamaindex-integration/.env.example b/examples/llamaindex-integration/.env.example new file mode 100644 index 000000000..c24f14f45 --- /dev/null +++ b/examples/llamaindex-integration/.env.example @@ -0,0 +1,31 @@ +# Cube Sandbox Configuration +# ========================= + +# Cube Sandbox API URL (default: local deployment) +E2B_API_URL=http://127.0.0.1:3000 + +# Cube Sandbox Template ID (required) +# Create a template with: +# cubemastercli tpl create-from-image \ +# --image cube-sandbox-cn.tencentcloudcr.com/cube-sandbox/sandbox-code:latest \ +# --writable-layer-size 1G \ +# --expose-port 49999 \ +# --expose-port 49983 \ +# --probe 49999 +CUBE_TEMPLATE_ID= + +# Optional: CubeProxy node IP for remote access +# CUBE_PROXY_NODE_IP= + +# Optional: SSL certificate file (for Cube's built-in mkcert) +# SSL_CERT_FILE=/root/.local/share/mkcert/rootCA.pem + +# LLM Configuration +# ================= + +# OpenAI API Key (for LlamaIndex Agent) +OPENAI_API_KEY=sk-your-api-key-here + +# Alternative: Use other LLM providers +# ANTHROPIC_API_KEY=sk-ant-... +# GOOGLE_API_KEY=... diff --git a/examples/llamaindex-integration/README.md b/examples/llamaindex-integration/README.md new file mode 100644 index 000000000..813301489 --- /dev/null +++ b/examples/llamaindex-integration/README.md @@ -0,0 +1,107 @@ +# LlamaIndex + CubeSandbox Integration Example + +## Overview + +This example demonstrates how to integrate Cube Sandbox as a secure code execution backend for LlamaIndex agents in RAG (Retrieval-Augmented Generation) workflows. + +## Features + +- **MicroVM-level isolation**: Code runs in a fully isolated virtual machine +- **Network security policies**: Configurable network access control to prevent data exfiltration +- **RAG data processing**: Safely process external data sources +- **Stateless/Stateful**: Supports single executions and multi-turn conversations + +## Installation + +```bash +pip install -r requirements.txt +``` + +## Configuration + +1. Copy the environment file: + ```bash + cp .env.example .env + ``` + +2. Edit `.env` with your configuration: + ```env + # Cube Sandbox API URL + E2B_API_URL=http://127.0.0.1:3000 + + # Cube Sandbox Template ID (required) + CUBE_TEMPLATE_ID= + + # OpenAI API Key for LLM + OPENAI_API_KEY=sk-... + ``` + +## Quick Start + +```python +from llamaindex_integration import create_cube_tool, create_rag_agent + +# Create Cube Sandbox tool +tool = create_cube_tool( + template_id="tpl-xxxx", + api_url="http://127.0.0.1:3000", +) + +# Create agent with code execution capabilities +agent = create_rag_agent( + template_id="tpl-xxxx", + api_url="http://127.0.0.1:3000", +) + +# Use agent to process tasks +response = agent.chat("Download a webpage and compute word frequency") +``` + +## Environment Setup + +### Option 1: Development Environment (Recommended) + +```bash +# Clone repository +git clone https://github.com/TencentCloud/CubeSandbox.git + +# Navigate to dev environment +cd CubeSandbox/dev-env + +# Prepare VM image (one-time only) +./prepare_image.sh + +# Start VM +./run_vm.sh + +# In a new terminal, login to VM +cd CubeSandbox/dev-env && ./login.sh + +# Inside VM: Install Cube Sandbox +curl -sL https://github.com/tencentcloud/CubeSandbox/raw/master/deploy/one-click/online-install.sh | bash + +# Create code interpreter template +cubemastercli tpl create-from-image \ + --image cube-sandbox-cn.tencentcloudcr.com/cube-sandbox/sandbox-code:latest \ + --writable-layer-size 1G \ + --expose-port 49999 \ + --expose-port 49983 \ + --probe 49999 + +# Monitor template creation +cubemastercli tpl watch --job-id + +# Note the output template_id +``` + +### Option 2: Direct Install (Linux Server) + +```bash +curl -sL https://github.com/tencentcloud/CubeSandbox/raw/master/deploy/one-click/online-install.sh | bash +``` + +## References + +- [Cube Sandbox GitHub](https://github.com/TencentCloud/CubeSandbox) +- [LlamaIndex Documentation](https://docs.llamaindex.ai/) +- [Python SDK](https://github.com/TencentCloud/CubeSandbox/tree/main/sdk/python) diff --git a/examples/llamaindex-integration/README_zh.md b/examples/llamaindex-integration/README_zh.md new file mode 100644 index 000000000..3a1ee232f --- /dev/null +++ b/examples/llamaindex-integration/README_zh.md @@ -0,0 +1,165 @@ +# LlamaIndex + CubeSandbox Integration Example + +## 功能 + +本示例演示如何将 Cube Sandbox 作为安全的代码执行后端,与 LlamaIndex Agent 集成,用于 RAG(检索增强生成)工作流。 + +## 特性 + +- **MicroVM 级隔离**:代码在完全隔离的虚拟机中执行 +- **网络安全策略**:可配置网络访问控制,防止数据泄露 +- **RAG 数据处理**:安全地处理外部数据源 +- **无状态/有状态**:支持单次执行和多轮对话 + +## 安装 + +```bash +# 安装依赖 +pip install -r requirements.txt +``` + +## 配置 + +1. 复制环境变量文件: + ```bash + cp .env.example .env + ``` + +2. 编辑 `.env` 文件,填入以下配置: + ```env + # Cube Sandbox API 地址 + E2B_API_URL=http://127.0.0.1:3000 + + # Cube Sandbox 模板 ID(创建模板后获取) + CUBE_TEMPLATE_ID= + + # 用于 Agent 的 LLM API Key + OPENAI_API_KEY=sk-... + ``` + +## 使用 + +### 基本用法 + +```python +from llamaindex_integration import create_cube_tool, create_rag_agent + +# 创建 Cube Sandbox 工具 +tool = create_cube_tool( + template_id="tpl-xxxx", + api_url="http://127.0.0.1:3000", +) + +# 创建带代码执行能力的 Agent +agent = create_rag_agent( + template_id="tpl-xxxx", + api_url="http://127.0.0.1:3000", +) + +# 使用 Agent 处理任务 +response = agent.chat("下载网页并计算词频") +``` + +### 网络隔离示例 + +```python +from cubesandbox import Sandbox, Config + +cfg = Config(api_url="http://127.0.0.1:3000", template_id="tpl-xxxx") + +# 完全禁用网络访问 +with Sandbox.create(config=cfg, allow_internet_access=False) as sb: + result = sb.run_code("print('Hello from isolated sandbox!')") + +# IP 白名单 +with Sandbox.create( + config=cfg, + allow_internet_access=False, + network={"allow_out": ["151.101.0.0/16"]}, +) as sb: + result = sb.run_code("import urllib.request; ...") +``` + +## 运行示例 + +```bash +# 运行完整演示 +python llamaindex_integration.py +``` + +## 环境设置 + +如需在本地运行 Cube Sandbox,请参考以下步骤: + +### 方式一:开发环境(推荐) + +```bash +# 克隆仓库 +git clone https://github.com/TencentCloud/CubeSandbox.git + +# 进入开发环境目录 +cd CubeSandbox/dev-env + +# 准备虚拟机镜像(仅首次) +./prepare_image.sh + +# 启动虚拟机 +./run_vm.sh + +# 新开终端,登录虚拟机 +cd CubeSandbox/dev-env && ./login.sh + +# 在虚拟机内安装 Cube Sandbox +curl -sL https://cnb.cool/CubeSandbox/CubeSandbox/-/git/raw/master/deploy/one-click/online-install.sh | MIRROR=cn bash + +# 创建代码解释器模板 +cubemastercli tpl create-from-image \ + --image cube-sandbox-cn.tencentcloudcr.com/cube-sandbox/sandbox-code:latest \ + --writable-layer-size 1G \ + --expose-port 49999 \ + --expose-port 49983 \ + --probe 49999 + +# 监控模板构建进度 +cubemastercli tpl watch --job-id + +# 记录输出的 template_id +``` + +### 方式二:直接安装(Linux 服务器) + +```bash +# 在 Linux 服务器上执行 +curl -sL https://cnb.cool/CubeSandbox/CubeSandbox/-/git/raw/master/deploy/one-click/online-install.sh | MIRROR=cn bash +``` + +## 架构图 + +``` + 用户脚本 (LlamaIndex + SDK) + | + ▼ + ┌─────────────────────────────┴─────────────────────────────┐ + │ │ + 【1. 管理流程 Control Plane】 【2. 调用流程 Data Plane】 + (如 Sandbox.create / delete) (如 run_code, commands.run) + │ │ + ▼ REST API (端口 3000) ▼ WSS / HTTP + CubeAPI CubeProxy + │ │ + ▼ │ + CubeMaster │ + │ │ + ▼ ┌────────────────────────────────────┐ │ + Cubelet ──────────────┼──► cube-agent ──► envd ◄──────────┼───┘ + │ (PID 1) │ │ + │ ▼ │ + │ Python / Shell │ + └────────────────────────────────────┘ +``` + +## 参考链接 + +- [Cube Sandbox GitHub](https://github.com/TencentCloud/CubeSandbox) +- [LlamaIndex 文档](https://docs.llamaindex.ai/) +- [Python SDK](https://github.com/TencentCloud/CubeSandbox/tree/main/sdk/python) diff --git a/examples/llamaindex-integration/llamaindex_integration.py b/examples/llamaindex-integration/llamaindex_integration.py new file mode 100644 index 000000000..1f28bfc3f --- /dev/null +++ b/examples/llamaindex-integration/llamaindex_integration.py @@ -0,0 +1,293 @@ +#!/usr/bin/env python3 +""" +LlamaIndex + CubeSandbox Integration Example + +This script demonstrates how to use Cube Sandbox as a secure code execution +backend for LlamaIndex agents in RAG workflows. + +Requirements: +- Python 3.9+ +- pip install llama-index llama-index-agent-openai e2b-code-interpreter python-dotenv + +Usage: +1. Set up Cube Sandbox environment (see README_zh.md for setup instructions) +2. Copy .env.example to .env and configure +3. Run: python llamaindex_integration.py +""" + +import os +import sys +from typing import Optional + +# Load environment variables from .env file if present +try: + from dotenv import load_dotenv + load_dotenv() +except ImportError: + pass + + +# ============================================================================= +# 1. Cube Sandbox Tool for LlamaIndex +# ============================================================================= + +def create_cube_tool( + template_id: str, + api_url: str = "http://127.0.0.1:3000", + proxy_node_ip: str = "", + timeout: int = 60, +) -> "FunctionTool": + """ + Create a LlamaIndex FunctionTool backed by a Cube Sandbox. + + Args: + template_id: Cube template ID (e.g. tpl-748094d2f2374b0a8a37e6ec) + api_url: CubeAPI address + proxy_node_ip: CubeProxy node IP for remote access + timeout: max execution time in seconds + + Returns: + LlamaIndex FunctionTool for code execution + """ + try: + from llama_index.core.tools import FunctionTool + from cubesandbox import Sandbox, Config + except ImportError as e: + print(f"Error: Missing required package. Install with:") + print(f" pip install llama-index cubesandbox") + sys.exit(1) + + def _run_code(code: str) -> str: + """Execute Python code in an isolated Cube Sandbox MicroVM.""" + cfg = Config( + api_url=api_url, + template_id=template_id, + proxy_node_ip=proxy_node_ip, + ) + try: + with Sandbox.create(config=cfg) as sb: + result = sb.run_code(code, timeout=timeout) + if result.error: + return f"Error: {result.error.name}: {result.error.value}" + return result.text or "" + except Exception as e: + return f"Execution error: {str(e)}" + + return FunctionTool.from_defaults( + fn=_run_code, + name="cube_sandbox", + description=( + "Executes Python code inside an isolated Cube Sandbox MicroVM. " + "Use this for untrusted code, RAG data processing, or any operation " + "that needs strong isolation. " + "Input: a single Python code string to execute. " + "Output: the result of the last expression or stdout/stderr." + ), + ) + + +# ============================================================================= +# 2. RAG Workflow with Code Execution +# ============================================================================= + +def create_rag_agent( + template_id: str, + api_url: str = "http://127.0.0.1:3000", + llm_model: str = "gpt-4o", +) -> "ReActAgent": + """ + Create a LlamaIndex ReAct agent with Cube Sandbox as code execution backend. + + Args: + template_id: Cube Sandbox template ID + api_url: CubeAPI address + llm_model: LLM model to use + + Returns: + Configured ReActAgent with code execution capabilities + """ + try: + from llama_index.core.agent import ReActAgent + from llama_index.llms.openai import OpenAI + except ImportError as e: + print(f"Error: Missing required package. Install with:") + print(f" pip install llama-index llama-index-agent-openai") + sys.exit(1) + + llm = OpenAI(model=llm_model) + cube_tool = create_cube_tool(template_id=template_id, api_url=api_url) + + agent = ReActAgent.from_tools( + tools=[cube_tool], + llm=llm, + verbose=True, + ) + return agent + + +# ============================================================================= +# 3. Example: Wikipedia Word Frequency Analysis +# ============================================================================= + +def example_wikipedia_analysis(agent: "ReActAgent") -> None: + """ + Example: Download Wikipedia page and compute word frequency statistics. + + This demonstrates a secure RAG workflow where: + - External data is fetched inside the isolated sandbox + - Code execution is sandboxed and cannot access host resources + - Network policies can restrict outbound connections + """ + query = """ + Download the Wikipedia page about Retrieval-Augmented-Generation (RAG), + parse it, and compute the top 10 most common words (excluding common stop words). + """ + print(f"\n{'='*60}") + print("Example: Wikipedia RAG Word Frequency Analysis") + print(f"{'='*60}") + print(f"Query: {query.strip()}\n") + + response = agent.chat(query) + print(f"\nAgent Response:\n{response}") + + +# ============================================================================= +# 4. Example: Data Processing Pipeline +# ============================================================================= + +def example_data_processing(agent: "ReActAgent") -> None: + """ + Example: Process JSON data and compute statistics. + """ + query = """ + Generate sample sales data for 3 products over 7 days, compute: + 1. Total revenue per product + 2. Daily average revenue + 3. Best performing day for each product + """ + print(f"\n{'='*60}") + print("Example: Sales Data Processing") + print(f"{'='*60}") + print(f"Query: {query.strip()}\n") + + response = agent.chat(query) + print(f"\nAgent Response:\n{response}") + + +# ============================================================================= +# 5. Example: Network Isolation for Security +# ============================================================================= + +def example_secure_execution() -> None: + """ + Example: Demonstrate network isolation for untrusted code. + + This shows how to configure Cube Sandbox with network policies to: + - Deny all outbound connections (no data exfiltration) + - Allow only specific IP ranges + """ + try: + from cubesandbox import Sandbox, Config + except ImportError: + print("Error: cubesandbox not installed. Run: pip install cubesandbox") + return + + template_id = os.getenv("CUBE_TEMPLATE_ID", "") + api_url = os.getenv("E2B_API_URL", "http://127.0.0.1:3000") + + cfg = Config(api_url=api_url, template_id=template_id) + + print(f"\n{'='*60}") + print("Example: Secure Execution with Network Isolation") + print(f"{'='*60}\n") + + # Example 1: No internet access + print("1. Sandbox with NO internet access:") + print("-" * 40) + print(""" + with Sandbox.create(config=cfg, allow_internet_access=False) as sb: + # Code here cannot access external networks + # Safe for untrusted data processing + result = sb.run_code("print('Hello from isolated sandbox!')") + """) + print("-" * 40) + + # Example 2: IP whitelist + print("\n2. Sandbox with IP whitelist (CIDR notation):") + print("-" * 40) + print(""" + with Sandbox.create( + config=cfg, + allow_internet_access=False, + network={"allow_out": ["151.101.0.0/16"]} # GitHub IPs only + ) as sb: + result = sb.run_code("import urllib.request; ...") + """) + print("-" * 40) + + +# ============================================================================= +# Main: Interactive Demo +# ============================================================================= + +def main(): + """Main entry point for the LlamaIndex + CubeSandbox demo.""" + print("=" * 60) + print("LlamaIndex + CubeSandbox Integration Demo") + print("=" * 60) + + # Load configuration from environment + template_id = os.getenv("CUBE_TEMPLATE_ID") + api_url = os.getenv("E2B_API_URL", "http://127.0.0.1:3000") + openai_key = os.getenv("OPENAI_API_KEY") + + if not template_id: + print("\n[ERROR] CUBE_TEMPLATE_ID not set!") + print("\nPlease set up Cube Sandbox and configure environment:") + print("1. Follow setup instructions in README_zh.md") + print("2. Create a template: cubemastercli tpl create-from-image ...") + print("3. Export CUBE_TEMPLATE_ID=") + print("\nFor now, showing network isolation examples only...") + example_secure_execution() + return + + if not openai_key: + print("\n[WARN] OPENAI_API_KEY not set. Using mock responses.") + print("Set OPENAI_API_KEY for full agent functionality.\n") + + print(f"\nConfiguration:") + print(f" API URL: {api_url}") + print(f" Template ID: {template_id[:20]}...") + print(f" LLM: gpt-4o\n") + + # Show network isolation examples + print("Showing network isolation configuration examples...") + example_secure_execution() + + if not openai_key: + print("\n[NOTE] Skipping agent examples - OPENAI_API_KEY not set.") + print("Set OPENAI_API_KEY to run full agent demonstrations.") + return + + # Create agent + try: + agent = create_rag_agent(template_id=template_id, api_url=api_url) + except Exception as e: + print(f"\n[ERROR] Failed to create agent: {e}") + print("Make sure Cube Sandbox is running at:", api_url) + return + + # Run examples + try: + example_data_processing(agent) + except Exception as e: + print(f"\n[ERROR] Data processing example failed: {e}") + + try: + example_wikipedia_analysis(agent) + except Exception as e: + print(f"\n[ERROR] Wikipedia analysis example failed: {e}") + + +if __name__ == "__main__": + main() diff --git a/examples/llamaindex-integration/requirements.txt b/examples/llamaindex-integration/requirements.txt new file mode 100644 index 000000000..fcb770a6e --- /dev/null +++ b/examples/llamaindex-integration/requirements.txt @@ -0,0 +1,12 @@ +# Core dependencies +llama-index>=0.10.0 +llama-index-agent-openai>=0.2.0 + +# Cube Sandbox SDK (E2B compatible) +e2b-code-interpreter>=0.0.20 + +# Optional utilities +python-dotenv>=1.0.0 + +# For local development +pytest>=7.0