跳至主要内容

Kimi K3.1 Pro API 教程:用 Python 构建自检式 3D CAD 智能体

使用 Kimi K3.1 Pro API 构建一个 Python 图像转 CAD 智能体:接入视觉输入、工具调用、Docker 沙箱、隐藏评测与成本跟踪。

使用 AI 探索

假设您有四张金属安装支架的照片——那种用于把搁板固定到墙上的 L 形支架——但没有对应的计算机辅助设计(CAD)文件。工程师之所以编辑 CAD 文件并将其发送到加工车间,是因为 CAD 文件能存储精确尺寸。您可以在 CAD 文件里移动一个孔或加宽一个槽,仍然能得到尺寸正确的零件;而仅凭图片做不到。

您需要的是一段简短的 Python 程序,基于已命名的尺寸(如 hole_diameter = 6.5)构建该支架,并将其保存为 STEP 文件——CAD 工具通用的标准格式。Moonshot 的技术博客称 Kimi K3.1 Pro 擅长此类空间任务,于是我做了一个测试:Kimi K3.1 Pro 能否把四张图片变成可编辑的 CAD 模型、用工具自检其结果、并在不破坏其他部分的前提下更改一个特征?

为公平起见,我用 CadQuery(一个用于构建 CAD 模型的 Python 库)亲自做了支架。我用它渲染了四张图片,并把原始 CAD 文件隔离,不让 Kimi 接触。在这篇 Kimi K3.1 Pro API 教程里,Kimi 将根据这些图片编写程序,而我的代码会运行它并测量其构建结果。

您不需要 CAD 背景也能跟上进度,但代码假定您熟悉 Python 和 Docker;几何细节出现时我会解释。我们将涵盖:

  • 通过 Chat Completions 把四张图片发给 Kimi,并获取 CadQuery 代码
  • 在 Docker 沙箱中安全运行这段代码
  • 为 Kimi 提供工具以测量并重绘其模型
  • 用 Kimi 未见过的隐藏参考对结果打分
  • 提出一次设计修改并检查移动了什么
  • 核算每次试验的成本

我们的Kimi K3.1 Pro 概览介绍了发布信息、基准测试、定价与访问方式,这里我将专注于智能体。

要点速览

我用 reasoning_effort="high" 设置,让 Kimi K3.1 Pro 三次把四张金属支架图片转成可编辑 3D 模型;除了一处小差异,三次结果一致:

  • 第一次就做对了。三次运行中,我测量的每个特征(如孔径与位置)都在原件的 0.5 毫米到 1.5 毫米之内,两者形状重合度超过 99.8%。
  • 自检帮助不大。Kimi 每次在自检后都直接批准提交,其中一次孔径小了 0.5 毫米也没改。
  • 编辑很简单。要求加宽一个槽后,只有该槽发生变化,其他部分不受影响。
  • 成本低。每次完整运行约 6 到 7 美分。

使用 Kimi K3.1 Pro API 构建图像转 CAD 智能体

图像转 CAD 智能体能把零件图片转成可编辑的 CAD 模型。

为什么 Kimi K3.1 Pro 与 CadQuery 适配图像转 CAD

Kimi K3.1 Pro 能读取四张图像,并对其自身代码的产物作出反应。我前面提到的同一篇 Moonshot 博客报告称,在BenchCAD 的 Vision2Code 任务上,使用工具得分为 92.7%,不使用工具为 72.8%,该任务从渲染视图编写 CAD 代码并计分。分数来自 1,000 个用例子集、在 max 努力级别下得到,且使用工具的成绩基于 Claude Code harness,因此部分得分可能归功于该 harness。

该基准还将四个视图并入一张图片,并在评分前把所有零件缩放到相同尺寸。我的做法是发送四个独立视图并提供一个真实尺寸,设置为 high 努力级别,因此把 Moonshot 的数字当作动手测试的理由,而非结果本身。当我运行这些试验时,开源权重尚不可下载。

之所以选择 CadQuery 作为输出格式,是因为 CadQuery 脚本本身就是参数化模型。一个孔对应一个包含直径与位置的调用,因此后续编辑只需改一个数,实体即可重建。STL 文件只有三角面,没有 slot_width 可改。

智能体能看到的与被隐藏的

Kimi 接收四张参考图、60 mm 的宽度信息,以及一段系统提示。该提示固定单位为毫米与坐标轴,把零件在 X 与 Y 居中、底面位于 Z=0,并要求给出命名尺寸以及在 result 中输出最终实体。

之后,Kimi 只知道工具报告的结果。Kimi API 不会运行 CadQuery,因此四个工具都在应用内实现:

  • execute_cad 在无网络的 Docker 容器中运行程序,并将结果保存为候选项

  • inspect_cad 报告有效性、实体数量、包围盒、体积以及圆柱面

  • render_cad 用与参考相同的四个相机视角渲染候选项

  • submit_cad 用一个候选项结束一个阶段

Kimi 从未见过参考代码或任何分数。评测器只会在智能体完成后读取已保存的 STEP 文件,因此分数既不能引导也不会中止智能体。

架构图:Kimi、四个本地 CAD 工具,以及不回传分数的隐藏评测器分数从不回流到 Kimi。作者供图。

在 Python 中设置 Kimi K3.1 Pro API

要在 Python 中使用 Kimi K3.1 Pro API,您需要四样东西。我在 Linux x86_64 上用以下版本完成了测试:

  • 一枚已充值至少 1 美元的 Kimi API 密钥,参考 K3.1 Pro 快速上手

  • Python 3.12.3 与 openai 3.39.0(OpenAI SDK)

  • cadquery 2.8.0(用于构建与检查实体)

  • Docker 29.9.2(用于沙箱)

下面的代码片段摘自该 GitHub 仓库的完整项目,您将很快克隆它。

安装 CadQuery 并构建 Docker 沙箱

CadQuery 的安装指南推荐使用 conda,不过在 Python 3.12 上用 pip 也可行。克隆仓库并完成设置:

git clone https://github.com/KhalidAbdelaty/Kimi_K3.1_Pro_API_Tutorial.git
cd Kimi_K3.1_Pro_API_Tutorial
python -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\Activate.ps1
pip install -r requirements.txt
cp .env.example .env             # then add your MOONSHOT_API_KEY
docker build -t cad-sandbox:2.8.0 sandbox/

该沙箱镜像安装相同版本的 CadQuery,并以普通用户身份运行。按 Docker 资源限制文档,Docker 默认不设 CPU 或内存限制,因此由运行器设置。仓库首页列出了运行与评分实验的命令,包括无需 API 密钥或 Docker 的路径。

在 Kimi 的代码进入容器之前,先尝试自己“破坏”它。我的测试程序尝试读取 API 密钥、访问网络、并在其临时文件夹之外写入,这三次尝试均被阻止。

Docker 沙箱中测试程序的终端输出,显示未找到 API 密钥、无法联网、且无法在目录外写入

沙箱中被拦截的三项操作。作者供图。

发出您的第一条 Kimi K3.1 Pro API 调用

这就是把 OpenAI SDK 指向 Moonshot 端点的常规用法。每次请求都要设置 reasoning_effort,因为留空会得到 max,而且您无法关闭“思考”。

client = OpenAI(api_key=os.environ["MOONSHOT_API_KEY"], base_url="https://api.moonshot.ai/v1")

response = client.chat.completions.create(
    model="kimi-k3.1-pro",
    reasoning_effort="high",        # low, high, or max; the API default is max
    max_completion_tokens=2048,     # reasoning and answer share this cap
    messages=[{"role": "user", "content": "In one sentence, what does a STEP file store?"}],
)
print(response.choices[0].message.content)
print("usage:", response.usage.model_dump(exclude_none=True))

不要设置 temperature、top_p、n,以及两个惩罚项;快速上手文档将它们列为固定值。即便是这样一句话的回答,完成的绝大部分 tokens 也花在推理上,因此设置上限时要考虑这一点。

一次 Kimi API 检查的终端输出,显示回答、完成原因与包含推理 tokens 的用量

一次请求确认密钥与模型。作者供图。

如果您对 Kimi API 还不熟悉,我之前的Kimi K3 教程涵盖了流式输出、工具调用、缓存与视觉输入。

创建参考 CAD 模型与四个测试视图

参考 CAD 模型是您的“答案标准”,每次评分都能与之精确对比。我在第一次请求前就把它锁定了——从相机到评分规则——看到结果后也未作任何更改。

定义支架尺寸

支架是 L 形,竖板与底板在后侧相连。原点位于底面中心,X 沿宽度方向、前方向为 −Y、Z 轴向上:

特征

数值

展示给 Kimi?

总体宽度(X)

60 mm

是

底板深度(Y)

40 mm

否

总体高度(Z)

45 mm

否

板厚

6 mm

否

安装孔

2 × Ø6.5 mm,间距 34 mm,位于 Y = −3 mm

否

竖板槽

宽 6 mm,端到端长度 20 mm,中心位于 X = 0,Z = 25.5 mm

否

我把孔排与槽都放在各自面的中线处,并采用 6.5 mm 孔径(常见的 M6 间隙孔尺寸),因为真实支架通常如此。这一选择最终成为本支架的薄弱点,我们稍后会解释原因。

在构建函数内,w、dep、h 与 t分别为宽度、深度、高度与厚度。它把两块板连接起来并切出这些特征:

base = cq.Workplane("XY").box(w, dep, t, centered=(True, True, False))
upright = cq.Workplane("XY").center(0, dep / 2 - t / 2).box(w, t, h, centered=(True, True, False))
holes = cq.Workplane("XY").pushPoints([(-17, -3), (17, -3)]).circle(3.25).extrude(t)
slot = (cq.Workplane("XZ", origin=(0, dep / 2 - t / 2, 0)).center(0, 25.5)
        .slot2D(20, 6, 90)            # end-to-end length, width, angle
        .extrude(t, both=True))
result = base.union(upright).cut(holes).cut(slot)

脚本会在导出 STEP 文件前检查是否得到一个尺寸正确的有效实体。

用固定相机渲染四个视图

一个小型 NumPy 渲染器以固定取景绘制正视、俯视、右视与等轴测视图,参考与每个候选都使用相同取景。在 512 像素下,一个像素约对应 0.19 mm,但从图像读数的误差可能超过该值。固定取景还能让过大或放错位置的候选显得“不对劲”,而不是被重新居中。

L 形安装支架的四个正交参考视图,底板有两个孔、竖板有一条槽

发送给 Kimi 的四张图片。作者供图。

在运行智能体前确定评测规则

评测器对导出的实体进行测量,因此参数名无法“误导”它。它会切片每个 STEP 文件以找到孔、槽与两处板厚,并在真实尺寸的 0.5 mm 体素网格上计算体素 IoU——两实体公共体积的占比。公差与像素尺度一致:板厚、孔径与槽宽为 ±0.5 mm,从图像读得的长度与位置为 ±1 到 ±1.5 mm。

仅靠 IoU 不够。我认为它是个“钝”指标,但由于没有更简单的方法比较两个实体,我仍在使用它。一个没有孔和槽的纯 L 形仍能拿到 0.96 以上,而把正确零件整体放大 20% 后,只要两者缩放到相同尺寸,IoU 也能是完美的 1.0。

因此这里每个得分都配有 13 项通过/未通过检查。即便 1.0 也只代表在该网格上两实体匹配,而非每微米都一致,这些数字都不构成制造保证。

用 Kimi K3.1 Pro 从图像生成 CadQuery 代码

第一个候选来自一条无工具的请求,并按返回内容原样运行。

向 Kimi K3.1 Pro API 发送四个参考视图

Kimi 的视觉输入在 content 数组中接受 base64 data URL,不接受公共图片 URL。系统提示包含我前述的取景与命名规则,用户消息携带四张 PNG 与如下提示:

These four images show one mechanical part, a bracket. Each view uses orthographic
projection, and all four use the same scale. The camera for each view is written at the
top of the image, and a small axis triad sits in the lower-left corner.

The overall width of the part along X is 60 mm. No other dimension is given, so estimate
the rest from the images.

Write one CadQuery program that rebuilds this part as an editable parametric model.
Return the complete program in a single python code block.

请求本身很简短:

images = [image_part(path) for path in view_paths]   # four PNGs as base64 data URLs
messages.append({"role": "user", "content": images + [{"type": "text", "text": BASELINE_PROMPT}]})
response = client.chat.completions.create(
    model="kimi-k3.1-pro", reasoning_effort="high",
    max_completion_tokens=32_768, messages=messages,
)

要在付费前检查输入大小,可将同一消息发送到token 预估端点,其估算值与账单几乎完全一致。四张 512 像素图像的输入不足 2,000 个 tokens。

在沙箱中运行第一段 CadQuery 程序

运行器把代码写入临时文件夹,并用 docker run 命令启动一次性容器:

cmd = ["docker", "run", "--rm", "--network", "none", "--read-only",
       "--tmpfs", "/tmp:size=64m", "--cap-drop", "ALL",
       "--security-opt", "no-new-privileges",
       "--memory", "1g", "--cpus", "1", "--pids-limit", "128",
       "-v", f"{work}:/work", "cad-sandbox:2.8.0"]
subprocess.run(cmd, capture_output=True, text=True, timeout=60)

在第一次试验中,Kimi 的回复用了约一分钟。其程序为隐藏参考中的每个尺寸都命了名,从 bracket_depth = 40.0 到 slot_center_z = 25.5 皆如此。它生成了有效实体并通过所有检查。

隐藏参考支架与 Kimi 首次重建的等轴测对比渲染,来自同一相机

同一相机、同一比例、形状匹配。作者供图。

第一次就完美让我检查是否“泄露”了信息,但 PNG 不含元数据,任何提示里也没有隐藏数值。Kimi 的代码解释了结果。正如我在定义支架时提到的,这些特征位于设计师通常会放置的位置,Kimi 亦如此。

Kimi 编写的 CadQuery 程序,将孔排和槽高作为支架面的中线求得

Kimi 通过中点推导特征位置。作者供图。

用 Kimi K3.1 Pro 构建自检式工具调用智能体

一个工具调用智能体以循环运行:Kimi 请求调用工具,您的代码执行它,并将结果作为工具消息返回,直到 Kimi 完成。

三个阶段的示意图:单次生成、修复循环与槽编辑,并标出每个阶段的停止条件

三个阶段,均有硬性限制。作者供图。

定义用于执行、检查与渲染 CAD 的工具

下面是 execute_cad 的模式。它用固定格式返回简短结果;当程序失败时,包含回溯的末几行:

{"type": "function", "function": {
    "name": "execute_cad",
    "description": "Run a complete CadQuery program in an isolated sandbox. Returns a "
                   "candidate id, whether it ran, and a short error if it did not.",
    "parameters": {"type": "object", "properties": {
        "code": {"type": "string",
                 "description": "The complete program. It must assign the final solid to result."}},
        "required": ["code"]}}}

render_cad 会在工具消息中直接返回四张图片,这与我们Agentic Vision 教程在 Gemini 中采用的“再看一眼”模式相同。Kimi 文档没有这种示例,因此将其视为“按观察到的行为”处理。在三次试验中,role: "tool" 消息都携带了 image_url 部分,且模型能读取。

在工具循环中保留完整的 assistant 消息

这里有三点很重要,前两点来自 Kimi 的思考型模型指南与快速上手:

  • 每一轮都回传完整的 assistant 消息,包括 reasoning_content 与 tool_calls

  • 每个工具调用添加一条工具消息,并带上对应的 tool_call_id

  • 用 model_dump() 序列化消息,因为 OpenAI SDK 没有类型化的 reasoning_content 字段

下面的循环遵循了这三点:

message = response.choices[0].message.model_dump(exclude_none=True)
messages.append(message)        # all of it, or the next turn quietly loses its reasoning
for call in message.get("tool_calls") or []:
    content = run_tool(call["function"]["name"], json.loads(call["function"]["arguments"]))
    messages.append({"role": "tool", "tool_call_id": call["id"], "content": content})

不要指望 API 在这里帮您抓错。把历史里的 reasoning_content 移除后,请求仍会成功,尽管文档要求该字段,且删除它可能改变后续轮次的延续方式。相比静默出错,我更希望返回 400。

预算写在循环的代码里,Kimi 无法更改。一旦 3 次修复用尽,execute_cad 将返回错误,而 submit_cad 会拒绝任何非“单一有效实体”的提交。

修复阶段发生了什么

几乎没发生什么——我差点因此删掉本节。我原以为修复循环会承担大部分工作,而 Kimi 几乎没用它。它检查了第一个候选、渲染了图像,写了一段自信的总结称其与四个参考视图匹配,然后提交了最初那份程序。

这段总结并非总是正确。在一次试验中,inspect_cad 报告孔半径为 3.0 mm,即孔径 6.0 mm,而参考为 6.5 mm,Kimi 仍然提交。半毫米在这些视图中不足 3 个像素(我自己肉眼看也不敢肯定),且反馈中没有指出正确直径是多少。

inspect_cad 工具的 JSON 报告,显示一个有效实体与 Z 轴方向孔面的 3.0 mm 半径

工具报告的半径为 3.0 mm。作者供图。

用 Kimi K3.1 Pro 编辑参数化 CAD 模型

由于修复循环几乎闲置,设计修改成了更能说明问题的测试。尽管这是一次温和的测试,如果一次修改会同时移动两个特征,难度会更大。

让 Kimi 加宽槽

编辑继续在同一会话中进行,并以 Kimi 提交的候选为起点,而非我的参考代码:

Increase the width of the vertical slot in the upright plate from 6 mm to 9 mm. 
Keep the slot's center position and its end-to-end length as they are in your model. 
Do not change the mounting holes, the plate thickness, or the outer dimensions.

Kimi 使用了 3 次允许程序中的一次。差异只是一行,将 slot_width = 6.0 改成 slot_width = 9.0,随后一轮检查与渲染,再提交。

在导出的几何体上检查编辑

代码里出现新数值并不能证明实体已改变。评测器在编辑前后逐体素比较了两个实体,只忽略允许由更宽槽占据的空间:

  • 槽宽为 9 mm,长度与中心不变
  • 孔、板厚与外形尺寸不变
  • 槽区外没有任何材料变化

每次编辑检查都全部通过。

编辑之所以干净,是因为 slot2D() 将长度视为端到端,因此槽仍为 20 mm 长,而直线段变短。若程序存的是两段圆弧圆心距,槽就会长出 3 mm。

Kimi 的支架在编辑前后的正视图,槽宽由 6.0 mm 加宽到 9.0 mm

只有槽发生了变化。作者供图。

Kimi K3.1 Pro CAD 智能体有多准?

在三次试验中,智能体都在我预先设定的公差内通过了所有隐藏检查。下表作为回顾:

检查项

三次试验结果

隐藏几何检查通过数

每次均为 13/13

与参考的体素 IoU(0.5 mm 网格)

0.998 至 1.0

孔径(真实值 6.5 mm)

两次为 6.5 mm,一次为 6.0 mm(Kimi 的复核放行了)

已用修复次数(允许 3 次)

0

编辑检查通过数

每次均为 8/8

三次试验不构成成功率,只说明在一个支架上结果具有稳定性。修复阶段出现的 6.0 mm 孔之所以通过,仅因为刚好卡在 ±0.5 mm 孔径公差上;若更严格,那次会失败。

自我纠错无事可做

要验证循环是否能改进模型,应进行“故障注入”测试,即从一个带已知错误的程序启动智能体。这与本次试验分开报告为宜。

每次试验的 token 成本与运行时间

每次试验包含 6 次请求与 7 次工具调用,费用为 6.3 至 7.3 美分。这里仅计 API 费用,渲染与 Docker 在我的机器上运行。

可按 usage 字段与 公布费率为 kimi-k3.1-pro 逐条计费。每百万 tokens:输入 $2.00,输出 $10.00,缓存命中 $0.20,5 分钟缓存写入 $2.00。

阶段

请求数

成本占比

首次请求

1

约一半

修复复核

2

约四分之一

编辑

3

约四分之一

首次请求成本最高,因为 Kimi 在这一轮进行推理。输出占账单过半,缓存写入占 23% 到 35%,而缓存命中几乎不花钱。以下展示三个输入字段如何相加,依据我先前链接的 Chat Completions 参考;如果您的追踪器已拆分缓存写入,可跳过。

uncached = u.prompt_tokens - cached - written   # the three parts sum to prompt_tokens
cost = (uncached * 2.00 + cached * 0.20 + written * 2.00 + u.completion_tokens * 10.00) / 1e6

推理 tokens 已计入 completion_tokens,不要重复计费。5 分钟缓存写入与未缓存输入同价,因此提示缓存只有在前缀被读回时才划算。工具循环每轮都会重发同一历史,这里缓存把输入费用降到原价的 40% 以下。

一次试验约耗时三分钟,主要在等待,因为客户端按我将在 FAQ 中说明的限速,每隔 21 秒发送一次请求。

基于图像的 AI CAD 生成有哪些不足

主要限制是图像无法承载所有尺寸信息。我的测试还增加了几点:

  • 渲染无法展示小于一个像素的细节。如果某个尺寸重要,请用文本给出或用工具测量。
  • 该支架容易猜。若孔不在中线、或尺寸怪异,就能测试 Kimi 是在读像素还是在套设计习惯。
  • Docker 标志只能拦截它们指明的内容。它们确实拦下了“设置”小节中的异常程序,但模型代码仍可能用满整整一分钟 CPU。我们的容器中保障 AI 智能体安全指南介绍了下一层防护。
  • 通过这些检查并不代表强度合格。载荷、材料、真实零件所需的圆角内角、螺栓配合以及公差叠加等均不在本测试范围内。

“易”这个特性更多是我测试的限制,而非 Kimi 的限制。

结语

我们构建了一个智能体:它能从四张图像编写参数化 CadQuery 代码、用工具检查其实体,并按要求编辑一个特征。对于这个支架,我开篇问题的答案是肯定的。三次试验均在首次请求内通过我设定的公差,而槽的编辑没有影响到零件的其他部分。

我无法为修复循环作背书,因为 Kimi 从未发现需要修复的内容。那次 0.5 mm 的误差之所以被它的复核放行,是因为它看到的是像素、而非真实直径。我不建议将结果泛化到尺寸怪异的零件,或真实照片。

值得借鉴的是方法论:隐藏参考,在第一次请求前冻结评分规则,并对导出的实体而非代码评分。Kimi 三次都称其候选匹配,只有评测器能判断两次“正确”、一次“接近”。我会保留这个评测器,而“故障注入”将是我首先要做的扩展。

若要进一步了解如何把模型连接到您自己的工具,我们的Developing AI Systems with the OpenAI API 课程涵盖了与本智能体相同 SDK 的函数调用。

常见问题解答

Kimi K3.1 Pro API 支持哪些图像格式与尺寸?

以 base64 data URL 发送 PNG、JPEG、GIF、WebP、BMP、HEIC 与 HEIF 均可,SVG 即便编码也会被拒绝,因此请把 SVG 图纸的 XML 作为文本发送。单个请求可携带任意数量的图像(总大小不超过 100 MB),我之前链接的视觉指南建议分辨率不超过 4096×2160。我建议避免发送动图 GIF 与 WebP,Kimi 可能会将其解码并按视频计费。

Kimi 的 3D Make 能替代这样的 CAD 智能体吗?

就发布博文来看,并不适合参数化工作。3D Make 位于 Kimi 应用与网站中,您可在其中编辑模型并下载以供 3D 打印。该博文未提及任何 API 访问或 STEP 导出,因此若要能更改 slot_width ,仍需要您自建工具循环。

为什么我的 Kimi K3.1 Pro 智能体会遇到 HTTP 429 错误?

先看 error.type,因为 Kimi 将 429 用于三种不同问题。rate_limit_reached_error 表示超过了您所在档位的限速,该限速从充值 1 美元时每分钟 3 次请求,提升到 10 美元时的每分钟 200 次。exceeded_current_quota_error 表示余额用尽,而 engine_overloaded_error 表示服务器繁忙,应退避重试,而非充值。

如何降低 Kimi K3.1 Pro CAD 智能体的成本?

默认 5 分钟缓存已适合此循环,因为每次命中都会免费续期,而我的请求间隔为 21 秒。若人工在轮次间审阅渲染内容、间隔可能超过 5 分钟,可参考上下文缓存指南将 TTL 设为 1 小时;其每百万 tokens 4 美元的写入成本,在两次命中后就能回本。若担心成本,我会跳过 Highspeed,因为它将价格翻倍,速度仅提升 2 到 3 倍。

CAD 重建应使用 high 还是 max 的推理强度?

建议从 high 开始,我在全文中都采用了它。若您尝试 max (我在本支架上未尝试),请开启流式响应,因为当非流式请求 900 秒内无输出时,网关会返回 504。完成上限默认为 131,072 个 tokens,包含推理,我设置的 32,768 上限可将单次回复的输出成本控制在约 33 美分以内。

Khalid Abdelaty

作者

Khalid Abdelaty

我是一名数据工程师兼社区建设者,专注于数据管道、云端与 AI 工具链,同时为 DataCamp 和新兴开发者撰写实用且高影响力的教程。

主题