
Khi nhờ AI viết mã Python để dựng mô hình 3D trong Blender, có hai thứ hay sai — và không thứ nào là hình học. Thứ nhất, API của Blender đã đổi sau thời điểm mô hình AI được huấn luyện, nên mã trông đúng nhưng chạy trên phiên bản Blender sai. Thứ hai, những lỗi quan trọng nhất của một mô hình 3D lại vô hình khi render: ảnh đẹp nhưng vật thể in 3D ra thì hỏng. Bài này tóm tắt và viết lại bằng tiếng Việt quy trình khắc phục hai vấn đề đó, theo thứ tự: ghim phiên bản, viết thẳng vào dữ liệu thay vì gọi thao tác giao diện, thống nhất đơn vị, kiểm đếm lỗi hình học bằng mã, rồi mới để AI "nhìn" kết quả.
Bài viết dựa trên bài "Opus 5.5 Writes Blender Python for the Wrong Blender - and the Render Won't Tell You" của @0xCodio trên X (11/10/2026), được OPCAIOS viết lại bằng tiếng Việt, rút gọn và diễn giải. Mọi số liệu benchmark, phiên bản phần mềm và thông tin bảo mật bên dưới là của tác giả gốc, OPCAIOS chưa kiểm chứng độc lập; hãy đối chiếu với tài liệu Blender hiện hành trước khi áp dụng vào công việc thật.

Vòng lặp trong bài: mỗi bước có một phép kiểm tra bằng máy, chỉ bước xem 6 góc mới dùng mắt (của AI). Sơ đồ: OPCAIOS.
Hai lỗi, không phải một
Lỗi 1 — nhắm sai phiên bản. Theo tác giả, một bài kiểm thử chạy 30 nhiệm vụ viết mã Blender trên bốn bản Blender với mười mô hình, mỗi đoạn mã đều được chạy thật ở chế độ không giao diện và có phép kiểm tra riêng — tổng cộng 1.190 câu trả lời được chấm. Kết quả:
- Tỉ lệ mã chạy được: 91% trên Blender 3.6, chỉ còn 70% trên Blender 5.0.
- Tỉ lệ mô hình còn nói đúng cái gì đã thay đổi: từ 81% tụt xuống 35%.
- Ba nhóm nhiệm vụ (compositor, bộ giải phép toán boolean, sequencer) bị 0 điểm ở mọi mô hình trên Blender 5.0.
Ví dụ rõ nhất: tên định danh của bộ render EEVEE đổi từ BLENDER_EEVEE sang BLENDER_EEVEE_NEXT ở bản 4.2, rồi quay lại BLENDER_EEVEE ở bản 5.0. Mô hình nào đã học đúng lần đổi tên giữa chừng thì giờ sai; mô hình nào chưa từng học thì lại đúng một cách ngẫu nhiên. Đây không phải lỗi suy luận mà là lỗi nhắm sai đích.
Lỗi 2 — lỗi vô hình khi render. Cạnh không kín (non-manifold), mặt có diện tích bằng không, các phần tự cắt nhau, khoang rỗng bên trong, thành mỏng hơn đầu phun máy in — tất cả vẫn render ra ảnh hoàn hảo. Tác giả dẫn trang chính thức của Blender về MCP, nơi chính họ ghi nhận mô hình AI từng bỏ sót một modifier Solidify làm gấp đôi số đa giác, vì modifier đó không ảnh hưởng đến khung nhìn.
Bước 1: ghim phiên bản trước mọi thứ khác
Bản hiện hành theo tác giả là Blender 5.2.2 LTS, và 4.5 là nhánh còn được bảo trì. Python đổi từ 3.11 lên 3.13 ở bản 5.1, và gói bpy chỉ chạy đúng một phiên bản Python — không có chuyện "gần đúng cũng được".
Khai báo phiên bản ngay trong prompt, rồi bắt chương trình tự chứng minh nó chạy đúng bản đó. Prompt hệ thống (system prompt) mẫu của tác giả:
Target Blender 5.2 LTS, Python 3.13. Do not use any API removed before it.
Rules:
- bpy.data and bmesh only; no bpy.ops.mesh.* and no bpy.ops.object.*
except where I have named one
- one Blender unit is one metre; declare MM = 0.001 and use it
- every dimension, clearance and wall thickness is a named module-level
constant, never inline
- boolean solver is EXACT unless I state the inputs are manifold
- end the script with the census asserts, not with a render
- after the code, list every API you used that changed in 4.0 or later
and state which release you are targeting for each
(Dịch ý: nhắm Blender 5.2 LTS / Python 3.13; chỉ dùng bpy.data và bmesh, không gọi thao tác giao diện; một đơn vị Blender là một mét và khai báo MM = 0.001; mọi kích thước là hằng số có tên; bộ giải boolean mặc định là EXACT; kết thúc script bằng các phép kiểm đếm chứ không phải bằng render; cuối cùng liệt kê mọi API đã đổi từ 4.0 và bản nào đang nhắm tới.)
Chạy Blender không giao diện bằng lệnh sau:
blender --background --factory-startup \
--python-exit-code 1 \
--python build.py -- --out ./dist --mm 20
Hai chi tiết tốn người ta mỗi chỗ một ngày:
- Thiếu
--python-exit-codethì lỗi trong script không làm đổi trạng thái thoát của Blender, nên hệ thống kiểm thử tự động (CI) báo xanh dù script đã sập. - Thứ tự tham số có ý nghĩa: đặt
-osau tên file.blend, nếu không việc mở file sẽ ghi đè đường dẫn đầu ra. Mọi thứ sau--được chuyển vào Python quasys.argv.
Bước 2: thao tác giao diện chỉ để cho người, script phải ghi thẳng vào dữ liệu
Theo chính tài liệu Blender mà tác giả trích: các "operator" (bpy.ops.*) không nhận dữ liệu làm tham số, chỉ trả về là đã xong hay chưa, và khi điều kiện chạy không thoả sẽ báo RuntimeError: ... context is incorrect mà không nói lý do. Khi chạy nền không có giao diện, mỗi lệnh bpy.ops.mesh.* đều tìm một ngữ cảnh chỉnh sửa mesh chưa tồn tại.
Vì vậy hãy bắt mô hình viết thẳng vào bpy.data và bmesh. Prompt sinh mã mẫu:
Build the part described below as a single Python file.
<spec: outer dimensions, wall, clearances, holes, tolerance, export path>
Output the parameter block first as a table. I will assert against it.
Bộ giải boolean cũng là một cái bẫy vì giá trị mặc định là cái bẫy: FLOAT được ghi rõ là "không hỗ trợ hình học chồng lấn", MANIFOLD chỉ chạy trên mesh kín, còn EXACT mới sống sót với đầu vào lộn xộn. Đưa hình học do AI sinh ra cho bộ giải mặc định không phải lỗi — đó là hành vi đã được tài liệu hoá.
Bước 3: lỗi sai tỉ lệ sống sót qua mọi lần xem lại
Lỗi sai gấp 100 lần trong âm thầm thường do ba sự thật cộng lại. Chọn quy ước đơn vị một lần, nói rõ ngay đầu script:
# 1 Blender unit = 1 metre. A 20 mm part is 0.02.
MM = 0.001
Tác giả nhấn mạnh trường hợp glTF: đặc tả bắt buộc đơn vị mét, trục Y hướng lên, và bộ xuất không có tuỳ chọn tỉ lệ nào — đơn vị Blender đi ra theo tỉ lệ 1:1, nên một đơn vị chính là một mét. Bảng "người ta tưởng — thực tế" theo tác giả:
| Người ta tưởng | Thực tế |
|---|---|
primitive_cube_add() tạo khối lập phương cạnh 1 đơn vị |
Tạo khối cạnh 2 đơn vị; size= là cả độ dài cạnh |
unit_settings.scale_length = 0.001 nghĩa là "làm việc bằng mm" |
Chỉ là hiển thị; hình học, vật lý và xuất file bỏ qua |
| Bộ xuất file mang theo đơn vị của bạn | STL và OBJ không mang đơn vị — bạn phải truyền use_scene_unit hoặc global_scale |
Bước 4: kiểm đếm bằng mã những gì ảnh render không trả lời được
Tác giả gọi là "census" (kiểm đếm): một khối mã chạy cuối script để đếm các lỗi vô hình và dừng cả quy trình nếu có lỗi.
import bmesh
bm = bmesh.new(); bm.from_mesh(obj.data)
nonmanifold = sum(1 for e in bm.edges if not e.is_manifold)
flipped = sum(1 for e in bm.edges if e.is_manifold and not e.is_contiguous)
loose = sum(1 for v in bm.verts if not v.link_faces)
degenerate = sum(1 for f in bm.faces if f.calc_area() <= 1e-4)
from mathutils.bvhtree import BVHTree
tree = BVHTree.FromBMesh(bm, epsilon=1e-5)
selfhit = len(tree.overlap(tree))
assert (nonmanifold, flipped, loose, degenerate, selfhit) == (0, 0, 0, 0, 0)
assert abs(obj.dimensions.x - 0.020) < 1e-5 # đúng kích thước đã yêu cầu
Khối mã này kiểm tra: cạnh không kín, cạnh có hướng mặt ngược, đỉnh lơ lửng, mặt suy biến, các phần tự cắt nhau, và kích thước đúng như đặc tả. Tác giả mô tả bộ kiểm đầy đủ là mười một câu hỏi mà một ảnh render không bao giờ trả lời được.
Vài điểm kỹ thuật đáng nhớ:
- Đo trước, nhìn sau. Một mã hay gặp là
bpy.ops.object.modifier_apply(modifier="Boolean"); trong chạy không giao diện, cách sống sót là lấy mesh đã được tính toán:dg = bpy.context.evaluated_depsgraph_get()rồiobj.evaluated_get(dg).to_mesh(). - Ngoài Blender, thư viện
trimeshcó thuộc tínhis_volume— nghĩa là vật thể kín, thứ tự các mặt nhất quán và pháp tuyến hướng ra ngoài. Yếu hơn làis_watertight, và thể tích chỉ có nghĩa với mesh đã là một khối đặc. - Công cụ kiểm tra in 3D (3D-Print Toolbox) không còn đi kèm Blender mà là tiện ích cộng đồng, nên quy trình chạy tự động phải tự cài nó. Ngưỡng mặc định (thành tối thiểu 1 mm, góc nhô (overhang) 45°) khớp với đồng thuận khi in 3D, nhưng chỉ đúng khi một đơn vị là một mét.
Bước 5: vòng lặp và các prompt điều khiển nó
Một lần lặp gồm: khối hệ thống đã lưu đệm, bản đặc tả, một lần sinh mã, một lần chạy không giao diện, phép kiểm đếm và một bản vá bằng số. Theo tác giả, một vòng như vậy tốn vài cent, còn lần chạy Blender chỉ tốn vài giây. Bảng giá được dẫn cho Opus 5.5 (mỗi 1 triệu token): đầu vào 4 USD, đầu ra 20 USD, đọc từ bộ nhớ đệm 0,20 USD, chạy theo lô 2 USD đầu vào và 10 USD đầu ra — hãy kiểm tra lại bảng giá hiện hành của nhà cung cấp.
Dựng ảnh để làm bảng tổng hợp, không phải để phán xét. Khi bước kiểm đếm đã qua, hãy tạo một ảnh ghép sáu góc nhìn của vật thể và đưa cho AI chỉ để chấm những thứ hình học không nói được: tỉ lệ so với kích thước đã nêu, chi tiết có nằm đúng chỗ không, phần nào trông như lơ lửng hay dính vào nhau, và thứ gì xuất hiện mà đặc tả không yêu cầu. Prompt phê bình mẫu:
Six orthographic views of one part: front, back, left, right, top,
three-quarter. The census already passed, so do not comment on topology.
Judge only what geometry cannot: proportion against the stated dimensions,
whether features sit where the spec says, parts that read as floating or
fused, and anything present that the spec did not ask for.
List discrepancies against: <parameter table>
Cách làm thực tế là dựng hình ngoài màn hình bằng GPU thay vì render đầy đủ, ghép sáu góc có tên vào một ảnh. Hai ràng buộc: Cycles không dựng được vào khung nhìn ngoài màn hình nên dùng EEVEE hoặc Workbench; và Blender 5.2 thêm gpu.init() đúng để lấy được GPU khi chạy --background.
Bước cuối là vá bằng số, không cho AI viết lại cả script:
Change constants in the parameter block only. Do not restructure, do not
rename, do not add geometry.
Apply exactly: <discrepancy list>
Return a diff.
Về MCP của Blender
Theo tác giả: hiện có máy chủ MCP chính thức từ Blender Lab (add-on v1.0.3, Blender 5.1 trở lên), và trang của họ tự cảnh báo rằng nó sẽ "chạy mã do mô hình sinh ra trong Blender mà không có hàng rào nào" và khuyên dùng máy ảo. Máy chủ cộng đồng có khoảng 28,7 nghìn sao trên GitHub, nói chuyện qua TCP thường ở localhost:9876 không xác thực, không mã hoá, và từng có lỗ hổng duyệt đường dẫn đã sửa ở bản 1.6.5. Kết luận của tác giả: coi cả hai là công cụ cho máy phát triển. Nếu bạn chưa quen MCP, đọc MCP là gì? trước.
Khi nhập mô hình do AI 3D sinh ra
Nếu mô hình đến từ một AI sinh 3D, hãy kiểm đếm kỹ hơn, không phải ít hơn. Theo tác giả, xu hướng 2026 đã rời khỏi hình học kín: TRELLIS.2 thậm chí quảng bá hình học không kín và bề mặt hở như một tính năng — phù hợp với quần áo, cây cỏ, sai với bất cứ thứ gì sẽ in. Không mô hình trả phí nào cam kết kín nước.
Chuỗi xử lý bằng script sau khi nhập, theo đúng thứ tự: kiểm tra hợp lệ → kiểm đếm → sửa bằng bmesh.ops (remove_doubles, recalc_face_normals, holes_fill, dissolve_degenerate) → chỉnh tỉ lệ và hướng → boolean → cuối cùng quadriflow_remesh hoặc voxel_remesh nếu cần topology dùng được.
Về các con số khi in 3D: bốn hướng dẫn công khai mâu thuẫn nhau gấp hai đến ba lần ở gần như mọi thứ. Chỉ có bốn con số tất cả cùng đồng ý — góc nhô (overhang) 45°, lỗ nhỏ nhất Ø2,0 mm, khe lắp ghép 0,5 mm, thành tối thiểu khoảng 1,0–1,2 mm. Hãy truyền bốn số đó làm tham số có tên, còn mọi số còn tranh cãi thì để làm đối số có giá trị mặc định. Một hằng số cứng trong bộ sinh mã đúng cho một máy in và sai cho máy in tiếp theo.
Tóm lại
Hai thứ đứng giữa một script trông như đã xong và một vật thể thật sự có mặt là: ghim phiên bản và bộ kiểm đếm bằng mã. Chúng không phải chi phí thừa; chúng là lý do một vòng lặp tốn vài cent có thể tin được. Áp dụng khuôn này ngoài Blender cũng đúng: khai báo rõ môi trường đích, để máy kiểm thứ máy kiểm được, và chỉ dùng mắt (của người hay của AI) cho phần máy không kiểm được.
Nguồn: @0xCodio trên X, 11/10/2026 — viết lại và rút gọn bởi OPCAIOS; số liệu, phiên bản, giá và thông tin bảo mật theo tác giả gốc, chưa kiểm chứng độc lập.
Để lại bình luận
Email của bạn sẽ không hiển thị công khai. Bình luận sẽ hiển thị sau khi được duyệt.


