Source code for scene_service.scene_graph.prompts

# SPDX-License-Identifier: MulanPSL-2.0
"""LLM prompts for scene graph relation inference."""
from __future__ import annotations

import json
from typing import Any

from .types import RELATION_TYPES, GeometryHint, SceneGraphNode

RELATION_SYSTEM_PROMPT = """\
You infer spatial relationships between two objects in a robot's 3D scene graph.

Return ONLY valid JSON.

Allowed relation values:
- "near": objects are spatially close but no stronger relation is clear.
- "on_top_of": source object is physically on top of target object.
- "under": source object is under target object.
- "inside": source object is inside target object.
- "contains": source object contains target object.
- "attached_to": source object is attached to or mounted on target object.
- "part_of": source object is a part/component of target object.
- "same_object": both detections likely refer to the same physical object.
- "none": no meaningful relation.
- "unknown": insufficient information.

Use geometry first. Use captions and common sense only as secondary evidence.
Do not invent objects not present in the input.

Output schema:
{
  "relation": "...",
  "confidence": 0.0,
  "reason": "brief explanation"
}
"""


[docs] def build_relation_user_prompt( a: SceneGraphNode, b: SceneGraphNode, hint: GeometryHint, ) -> str: """Build the user message payload for one object pair.""" payload: dict[str, Any] = { "object_a": { "id": a.object_id, "label": a.label, "caption": a.caption or a.label, "bbox_center": list(a.bbox_center), "bbox_extent": list(a.bbox_extent), }, "object_b": { "id": b.object_id, "label": b.label, "caption": b.caption or b.label, "bbox_center": list(b.bbox_center), "bbox_extent": list(b.bbox_extent), }, "geometry_hint": { "distance": round(hint.distance, 3), "xy_overlap": round(hint.xy_overlap, 3), "vertical_order": hint.vertical_order, "containment": hint.containment, }, "instruction": ( "Infer the relation from object_a to object_b. " "If object_a is on object_b, return relation='on_top_of'. " "If object_a is inside object_b, return relation='inside'. " "Return exactly one JSON object with keys: relation, confidence, reason." ), } return json.dumps(payload, ensure_ascii=False)