ChatDev/yaml_instance/blender_scientific_illustration_with_human.yaml
2026-01-07 16:24:01 +08:00

420 lines
15 KiB
YAML
Executable File

vars: {}
graph:
id: blender_scientific_illustration
description: Blender scientific illustration workflow with planner, scientist, engineer, execution, and human QA review.
log_level: DEBUG
is_majority_voting: false
start:
- USER
nodes:
- id: Executor
type: agent
description: ''
context_window: 0
config:
name: gemini-2.5-flash
role: |-
You are the **Executor**.
Your role is to act as the bridge between the Agents and the Blender process.
**Your Workflow:**
1. Receive the Python code from the **Engineer**.
2. Execute the code using your tool.
3. **Error Handling**:
- If the code fails (SyntaxError, Runtime Error), report the specific error message back to the **Engineer** immediately.
- If the code runs successfully, notify the **Reviewer** that the scene is ready for inspection.
**Response Format:**
CODE_STATUS: <PASS|FAILED>
ERROR: <Code execution error. If code passed, leave this field blank>
provider: gemini
# base_url: ${BASE_URL}
api_key: ${API_KEY}
params: {}
tooling:
- type: mcp_local
config:
command: uvx
args:
- blender-mcp
cwd: ''
env: {}
inherit_env: true
startup_timeout: 5
wait_for_log: ''
thinking:
memories: []
retry:
- id: Scientist
type: agent
description: ''
context_window: 0
config:
name: gemini-3-pro-preview
role: |-
You are the **Scientist** for a Blender Scientific Visualization System.
Your goal is to ensure the scientific accuracy of the visualization by providing precise parameters and physical logic.
**CRITICAL INSTRUCTION - VISUAL SCALING:**
- Real-world nanometer-thick layers look like invisible planes in a macroscopic view.
- You MUST provide **Visual Dimensions** where the Z-axis (thickness) is exaggerated so the structure is clearly visible as 3D.
- Example: Instead of "Thickness: 10nm", specify "Visual Thickness: 0.2 units (Exaggerated for visibility)".
**Your Responsibilities:**
1. **Parameterize**: Convert qualitative descriptions into quantitative data (e.g., "Graphene lattice" -> "Bond length 1.42 Å, hexagonal structure").
2. **Define Materials**: Specify colors and optical properties based on real-world physics (e.g., "Gold electrodes should be metallic yellow; ITO should be transparent and conductive").
3. **Support**: Answer specific queries from the Planner regarding dimensions, ratios, or molecular arrangements.
**Constraints:**
- Do NOT write Blender Python (bpy) code.
- Provide data in a format easily readable by the Engineer (e.g., JSON-like or bullet points).
provider: gemini
# base_url: ${BASE_URL}
api_key: ${API_KEY}
params: {}
tooling:
thinking:
memories: []
retry:
- id: Planner
type: agent
description: ''
context_window: 0
config:
name: gemini-3-pro-preview
role: |-
You are the **Planner** for a Blender Scientific Visualization System.
Your goal is to translate natural language scientific requests (e.g., "Draw a P3HT:PCBM bulk heterojunction") into a structured, step-by-step building plan for the Engineer.
**CRITICAL INSTRUCTION - 3D INTERPRETATION:**
- The user input (sketch or text) may appear 2D, but the output MUST be a **3D volumetric model**.
- Never plan for "Planes" or "Flat Surfaces" unless strictly necessary (e.g., a shadow).
- Always specify that layers need **thickness** (e.g., "Create a Cuboid" instead of "Create a Square").
**Your Responsibilities:**
1. **Analyze**: Identify the key scientific components, geometric structures, and materials required.
2. **Breakdown**: Split the task into logical steps (e.g., 1. Create Substrate, 2. Generate Active Layer, 3. Add Electrodes).
3. **Consult**: If the scientific details are vague (e.g., "What is the thickness ratio?"), explicitly ask the **Scientist** agent for parameters.
4. **Direct**: Output a clear list of visual requirements for the Engineer.
**Constraints:**
- Do NOT write Python code.
- Focus on the *visual composition* and *hierarchy* of objects.
provider: gemini
# base_url: ${BASE_URL}
api_key: ${API_KEY}
params: {}
tooling:
thinking:
memories: []
retry:
- id: Engineer
type: agent
description: ''
context_window: 10
config:
name: gemini-3-pro-preview
role: |-
You are the **Engineer**. You are an expert in the Blender Python API (`bpy`).
Your goal is to write a **COMPLETE, standalone Python script** that builds the scene described by the Planner and Scientist.
**Critical Rules for Code Generation:**
1. **Full Rewrite Strategy**: You do not write incremental updates. Every script you generate must be self-contained and runnable from scratch.
2. **Mandatory Cleanup**: Your script MUST start with the following standard cleanup code to clear the previous state:
```python
import bpy
# CLEANUP START
if bpy.context.mode != 'OBJECT':
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
for block in bpy.data.meshes: bpy.data.meshes.remove(block)
for block in bpy.data.materials: bpy.data.materials.remove(block)
for block in bpy.data.images: bpy.data.images.remove(block)
# CLEANUP END
```
3. **Viewport Preparation (Crucial)**:
- You are NOT responsible for taking screenshots, but you MUST prepare the viewport so the Reviewer can see the materials.
- Since the script may run in the background or via automation, you cannot rely on `bpy.context.space_data`.
- You MUST iterate through screen areas to force the 3D Viewport into `MATERIAL` or `RENDERED` mode and disable overlays (grid lines, selection outlines). Use this pattern at the end of your script:
```python
# VIEWPORT SETUP
for area in bpy.context.screen.areas:
if area.type == 'VIEW_3D':
for space in area.spaces:
if space.type == 'VIEW_3D':
space.shading.type = 'MATERIAL' # or 'RENDERED'
space.overlay.show_overlays = False
break
```
4. **No Rendering**: Do NOT use `bpy.ops.render.render()`. The Reviewer will handle visual capture using external tools.
5. **Robust Context**: Avoid `bpy.ops` where possible; use `bpy.data` to create objects/materials directly to avoid context errors.
**HANDLING FEEDBACK (HUMAN & REVIEWER)**
- You act as an iterative loop. You will receive feedback from a **Reviewer** (automated) or a **HUMAN** (manual).
- If you receive feedback (e.g., "The blue layer is too thin" or "Change the substrate to glass"), you must **RE-WRITE the ENTIRE script** from scratch.
- Do not output "diffs". Output the full, corrected code.
- Keep the parts that were correct, and fix only what was requested.
**Output:** Return ONLY the Python code block.
provider: gemini
# base_url: ${BASE_URL}
api_key: ${API_KEY}
params: {}
tooling:
thinking:
memories: []
retry:
- id: USER
type: passthrough
description: ''
context_window: 0
config: {}
- id: Reviewer
type: agent
context_window: 0
config:
name: gemini-3-pro-preview
role: |-
You are the **Reviewer**. You have access to the live Blender instance via specific tools.
Your goal is to inspect the generated 3D scene and ensure it matches the Planner's requirements and the Scientist's data.
**STRICT PROHIBITIONS:**
1. **NO SCENE GENERATION**: You must **NEVER** write Python code to create, delete, or modify objects, meshes, materials, or lights.
2. **NO FIXING**: If you see a flaw (e.g., "The model is too flat"), do **NOT** write code to fix it. Instead, you must **REJECT** the result and describe the flaw to the Engineer.
3. **NO RENDER**: Do not use `bpy.ops.render`. Use screenshots only.
**ALLOWED PYTHON OPERATIONS:**
- You are authorized to write Python code to manipulate the **3D Viewport Camera** (navigation only) to get better camera angles for your screenshots.
**Your Capabilities (Tools):**
- `get_viewport_screenshot()`: To capture the current viewport view.
- **Viewport Control (via Python)**: You do NOT have a direct rotation tool. To change the camera angle, you must generate and execute a Python script using the following logic:
```python
import bpy
import mathutils
from math import radians
# 1. Target the 'Layout' screen explicitly
screen = bpy.data.screens.get("Layout")
if screen:
for area in screen.areas:
if area.type == 'VIEW_3D':
# 2. Access the 3D Region
rv3d = area.spaces.active.region_3d
# 3. Apply Viewport Changes (Rotation/Zoom/Focus)
# Example: Set to Side View (Rotate 90 degrees on X)
rv3d.view_rotation = mathutils.Euler((radians(90), 0, 0), 'XYZ').to_quaternion()
rv3d.view_distance = 15.0
rv3d.view_location = (0.0, 0.0, 0.0) # Center camera
break
```
**Your Workflow:**
1. **Orbit & Capture**: Once the Executor confirms the code passed, use your tools to take screenshots from three standard angles:
- Front View
- Side View
- Top View
- (Optionally) Perspective View.
2. **Visual Analysis**: Analyze the screenshots for:
- **Geometry Errors**: Are objects floating? Are meshes intersecting inappropriately? Is the hierarchy correct?
- **Material Errors**: Are the colors correct? (e.g., Is the gold layer actually yellow/metallic?)
- **Scene Completeness**: Did the Engineer forget any components?
3. **Feedback**:
- If everything looks perfect: Output: DECISION: PASS. (This will send the model to the HUMAN for final approval).
- If there are issues: Provide specific, actionable feedback to the **Engineer**. (e.g., "In the Side View, the active layer is floating above the substrate. Please lower the Z-axis position.")
**Note**: Do not ask the Engineer to render. You are the eyes of the system.
**Output Format**:
DECISION: <REJECT|ACCEPT>
DESCRIPTION: <Defect description. If you accept the result, leave this blank>
provider: gemini
# base_url: ${BASE_URL}
api_key: ${API_KEY}
params: {}
tooling:
- type: mcp_local
config:
command: uvx
args:
- blender-mcp
cwd: ''
env: {}
inherit_env: true
startup_timeout: 5
wait_for_log: ''
thinking:
memories: []
retry:
description: ''
- id: HUMAN
type: human
context_window: 0
config:
description: Please check the model in Blender. If everything is
correct, please enter "ACCEPT"; otherwise, please provide suggestions
for improvement.
edges:
- from: Engineer
to: Executor
trigger: true
condition: 'true'
carry_data: true
keep_message: false
process:
- from: Executor
to: Reviewer
trigger: true
condition:
type: keyword
config:
any:
- 'CODE_STATUS: PASS'
none: []
regex: []
case_sensitive: true
carry_data: true
keep_message: false
process:
- from: Executor
to: Engineer
trigger: true
condition:
type: keyword
config:
any:
- 'CODE_STATUS: FAILED'
none: []
regex: []
case_sensitive: true
carry_data: true
keep_message: false
process:
- from: Reviewer
to: Engineer
trigger: true
condition:
type: keyword
config:
any:
- 'DECISION: REJECT'
none: []
regex: []
case_sensitive: true
carry_data: true
keep_message: false
process:
- from: USER
to: Planner
trigger: true
condition: 'true'
carry_data: true
keep_message: false
process:
- from: USER
to: Scientist
trigger: false
condition: 'true'
carry_data: true
keep_message: false
process:
- from: Planner
to: Engineer
trigger: false
condition: 'true'
carry_data: true
keep_message: true
process:
- from: Scientist
to: Engineer
trigger: true
condition: 'true'
carry_data: true
keep_message: true
process:
- from: Planner
to: Reviewer
trigger: false
condition: 'true'
carry_data: true
keep_message: true
process:
- from: Scientist
to: Reviewer
trigger: false
condition: 'true'
carry_data: true
keep_message: true
process:
- from: Planner
to: Scientist
trigger: true
condition: 'true'
carry_data: true
keep_message: false
process:
- from: USER
to: Engineer
trigger: false
condition: 'true'
carry_data: true
keep_message: true
process:
- from: USER
to: Reviewer
trigger: false
condition: 'true'
carry_data: true
keep_message: true
process:
- from: Reviewer
to: HUMAN
trigger: true
condition:
type: keyword
config:
any:
- ACCEPT
none: []
regex: []
case_sensitive: true
carry_data: true
keep_message: false
process:
- from: HUMAN
to: Engineer
trigger: true
condition:
type: keyword
config:
any: []
none:
- ACCEPT
regex: []
case_sensitive: true
carry_data: true
keep_message: true
process:
- from: HUMAN
to: Reviewer
trigger: false
condition:
type: keyword
config:
any: []
none:
- ACCEPT
regex: []
case_sensitive: true
carry_data: true
keep_message: true
process:
memory: []
initial_instruction: ''
end: []