Code Interpreter
代码 API 统一执行 Python 和 JavaScript。调用时传入语言和代码,daemon 会选择对应的运行时并返回结果。
可用运行时包括原生 REPL、内嵌 IPython kernel 和外部 Jupyter 兼容服务。daemon 会根据语言和当前配置选择运行时,调用方不需要指定具体后端。
代码会话(code session)在多次调用之间保持解释器进程存活:上一次调用定义的东西,下一次还在。不带会话时,每次执行都是一次性的,进程用完即弃。
需要执行 shell 命令而不是一段代码时,用 Commands。v1 和 v2 路由的对照见 从 1.x 迁移。
运行要求
GET /v1/capabilities 在 code_interpreter 下描述该 plane:
status—— 任一解释器能应答就是ready,都没有时是absentbackend—— 运行 Python 的是哪一层:native、kernel或endpointkinds——code、nodejs,kernel 支撑 Python 时还有jupyterdefault_python、default_node—— 原生层实际启动的二进制
原生层需要 PATH 上有 python3 或 node;kernel 层还需要能 import 的 ipykernel。daemon 会根据可用的运行时选择对应的执行层。
执行代码
请求体示例:
请求体示例:
请求体包含以下字段:
language 也接受 python3、node、nodejs 和 js;路由不认识的字段会被忽略。
如果 daemon 无法切换到请求指定的 user,这不属于请求格式错误。请求仍返回 HTTP 200,但 status 为 error,并在 ProcessError 输出中说明只有 root 可以切换身份。
kernel 会忽略 user,始终使用 daemon 自己的账户运行。
data 包含:
language、code—— 解析出的语言,以及实际执行的代码status——ok、error或timeoutoutputs—— notebook 输出列表,执行产生的每样东西一条stdout、stderr—— 各自独立的流;为空时 v2 是"",v1 是nullexit_code—— 正常执行完是0;报错或超时后是1execution_count—— 会话的 cell 计数器,从 1 开始session_id—— 运行它的会话;一次性执行时是null
status 表示本次执行结果,返回结构中的 success 与它对应。
代码抛出异常或执行超时仍返回 HTTP 200,但 success 为 false。
空的 code 字符串是 v1 和 v2 的一个差异:v2 返回 422;v1 会执行空 cell,返回 200,且没有输出。
outputs 是 notebook 输出列表:
JavaScript 就是换一个 language 的同样请求:console.log([1, 2, 3].reduce((a, b) => a + b, 0)); 同样打印 6。
另有两个按语言拆分的路由,执行相同的代码,但会话语义不同:
POST /v1/jupyter/execute使用真正的 IPython kernel,支持 magic 命令和富输出。POST /v1/nodejs/execute使用 JavaScript REPL。
运行时信息
两个接口返回同一份 body —— 当前生效的后端、语言和上限:
backend—— 这里运行 Python 的是哪一层:native、kernel或endpointkinds—— 存在的运行时:python、nodejs,有 kernel 时还有jupyterlanguages——language接受哪些值python、node—— 各是{available, version}max_sessions—— 同时最多能开多少个会话default_timeout、max_timeout——30和900prewarmed—— 有多少个预热进程在等着;默认是0
在调用之间保留状态
daemon 没见过的 session_id 会在请求时创建。只传 stateful: true 时,响应会返回一个生成的 id。
会话状态保存在内存中:同一会话内会跨调用保留,但会在 aiod 重启后消失。
会话条目包含:
session_id、language、cwd—— 它是什么,在哪里运行created_at、last_used—— 毫秒时间戳age_seconds—— 距离上次执行过了多少秒max_idle_time—— 关闭前允许空闲的毫秒数state——idle或executing
kernel 支撑的 Python 会话也列在这里,带的是 kernel_name 而不是 max_idle_time。
下面展示共用同一个会话的两次调用。Aio 是 Examples 中用于解析返回结构的辅助客户端:
kernel 支持 Python 时,code 会话和 Jupyter 会话可以共享命名空间。两边使用同一个 session_id,例如 {"session_id": "s1"},就会访问同一个 kernel;任一接口都可以结束该会话。
常见用法
大多数执行都是一次性的。
超时与上限
执行超过 timeout 时,返回结果中的 status 为 "timeout"。超时后的处理方式和资源开销取决于后端:
原生层会在超时后再等待 5 秒,然后终止解释器。
如果执行在这段时间内结束,仍然可以读取输出;会话会保留,但命名空间会重置。
kernel 层只中断当前 cell,kernel 和此前定义的内容都会保留。
两组上限分别由以下配置控制:
- 原生 REPL:
AIO_CODE_MAX_SESSIONS、AIO_CODE_SESSION_TIMEOUT_SECS - kernel:
AIO_KERNEL_MAX_SESSIONS、AIO_KERNEL_SESSION_TIMEOUT_SECS
超过对应上限时返回 429,已有会话不会被清除。返回消息分别是 Maximum number of sessions (20) reached 和 Maximum number of kernel sessions (5) reached。
选择后端
Python 按以下顺序选择后端:
AIO_JUPYTER_ENDPOINT指向的外部 Jupyter 兼容端点,能连通时用它- 内嵌 kernel,装了
ipykernel时用它 - daemon 原生的 Python REPL
JavaScript 始终使用原生 REPL,只要 PATH 中存在 node 即可。
默认不预热任何后端。AIO_CODE_PREWARM 和 AIO_KERNEL_PREWARM 的默认值都是 0。
AIO_CODE_BACKEND(auto、native、kernel)可以固定 Python 后端,跳过上述顺序。
扩展更多语言
language 接受 python(也接受 python3)和 javascript(也接受 node、nodejs、js),其他值返回 422。要运行其他语言,可以按实现成本选择以下三种方式:
- 任意解释器,不保留状态。 通过 Commands 当成命令来跑,比如
ruby -e "puts 1"。不需要任何配置,只是没有会话状态,输出也不是 notebook 的格式。 - 换一个 Python 或 Node 版本。
PYTHON_VERSION/NODE_VERSION决定原生层从PATH上选择哪个python3/node。/v1/jupyter使用kernel_name从已安装的 kernel 中选择。见 Jupyter。 - 为 code plane 增加语言支持。 原生层每种语言只有一个很小的、只用标准库的 harness,编译进二进制(
harness.py、harness.js)。
daemon 向 harness 的 stdin 逐行写入 {"code", "timeout_ms"},再从 stdout 逐行读取 {"stdout", "stderr", "result", "error"}。
每个会话对应一个进程。
新增语言时,需要为对应解释器编写这样的 harness,并在 daemon 的 Language 列表中登记。
HTTP 接口、会话、超时和上限都可以复用现有实现。
错误处理
代码异常、执行超时和解释器进程崩溃都会返回 HTTP 200,并将 success 设为 false;status 为 error 或 timeout。
只有请求本身无效时才返回错误状态码:
v2 拒绝请求时,原因写在 message 中,例如 Unsupported language 'ruby'. Supported: python, javascript。
v1 将同样的原因放在 errors 列表中。每个被拒绝的字段占一项,并带有 location: ["body", "language"] 和 type: "enum"。
跨接口的通用约定见 错误处理。