|
|
|
@@ -18,7 +18,7 @@ logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
# ── System prompt ────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
SYSTEM_PROMPT = """You are the Schaeffler Automat AI assistant. You help users manage their automated render pipeline for Schaeffler product images.
|
|
|
|
|
SYSTEM_PROMPT = """You are the HartOMat AI assistant. You help users manage their automated render pipeline for HartOMat product images.
|
|
|
|
|
|
|
|
|
|
You can:
|
|
|
|
|
- List and search orders and products
|
|
|
|
@@ -39,8 +39,8 @@ RULES:
|
|
|
|
|
7. Respond in the same language the user writes in.
|
|
|
|
|
8. Be concise — short answers are better than long ones.
|
|
|
|
|
9. When the user says "beliebig", "any", "random", "irgendein" — just pick one yourself, don't ask back.
|
|
|
|
|
10. Material system: Materials have SCHAEFFLER library names (e.g. SCHAEFFLER_020101_Durotect-Blue). Common names like "Durotect", "Stahl", "Bronze" are aliases that map to these library names. When the user asks for a material by a common name, use list_materials to find the correct SCHAEFFLER name, then use that for material_override.
|
|
|
|
|
11. When setting material_override, always use the full SCHAEFFLER library name (e.g. SCHAEFFLER_020101_Durotect-Blue), never the alias.
|
|
|
|
|
10. Material system: Materials have HARTOMAT library names (e.g. HARTOMAT_020101_Durotect-Blue). Common names like "Durotect", "Stahl", "Bronze" are aliases that map to these library names. When the user asks for a material by a common name, use list_materials to find the correct HARTOMAT name, then use that for material_override.
|
|
|
|
|
11. When setting material_override, always use the full HARTOMAT library name (e.g. HARTOMAT_020101_Durotect-Blue), never the alias.
|
|
|
|
|
12. When mentioning a product, ALWAYS link to it: [ProductName](/products/UUID). When mentioning an order, link to it: [OrderNumber](/orders/UUID). This makes the response navigable.
|
|
|
|
|
13. Materials exist at TWO levels: (a) product_material — materials assigned to the product's CAD parts (from STEP/Excel import, e.g. "Durotect_M", "Stahl"), and (b) material_override — a single material applied to ALL parts at render time. When user asks for a product "with Durotect material", search product_material FIRST (products that naturally have Durotect parts). Only use material_override filter if they specifically say "override" or "alle Teile in".
|
|
|
|
|
14. NEVER say "no renders found" when renders DO exist. If no exact match, show the closest match and explain what's different."""
|
|
|
|
@@ -120,7 +120,7 @@ TOOLS = [
|
|
|
|
|
},
|
|
|
|
|
"material_override": {
|
|
|
|
|
"type": "string",
|
|
|
|
|
"description": "Optional SCHAEFFLER library material name to apply to all lines.",
|
|
|
|
|
"description": "Optional HARTOMAT library material name to apply to all lines.",
|
|
|
|
|
"default": "",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
@@ -176,7 +176,7 @@ TOOLS = [
|
|
|
|
|
},
|
|
|
|
|
"material_name": {
|
|
|
|
|
"type": "string",
|
|
|
|
|
"description": "SCHAEFFLER library material name, or empty string to clear.",
|
|
|
|
|
"description": "HARTOMAT library material name, or empty string to clear.",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"required": ["order_id", "material_name"],
|
|
|
|
@@ -250,7 +250,7 @@ TOOLS = [
|
|
|
|
|
"type": "function",
|
|
|
|
|
"function": {
|
|
|
|
|
"name": "list_materials",
|
|
|
|
|
"description": "List available SCHAEFFLER library materials with their aliases. Use this to find the correct material name for material_override. Materials have names like SCHAEFFLER_010101_Steel-Bare. Aliases map common names (Stahl, Bronze, Durotect, etc.) to these library materials. When user asks for a material by a common name, search aliases to find the correct SCHAEFFLER library material name.",
|
|
|
|
|
"description": "List available HARTOMAT library materials with their aliases. Use this to find the correct material name for material_override. Materials have names like HARTOMAT_010101_Steel-Bare. Aliases map common names (Stahl, Bronze, Durotect, etc.) to these library materials. When user asks for a material by a common name, search aliases to find the correct HARTOMAT library material name.",
|
|
|
|
|
"parameters": {
|
|
|
|
|
"type": "object",
|
|
|
|
|
"properties": {
|
|
|
|
@@ -671,13 +671,13 @@ async def _tool_check_materials(db: AsyncSession, tenant_id: str, user_id: str =
|
|
|
|
|
async def _tool_list_materials(db: AsyncSession, tenant_id: str, query: str = "") -> str:
|
|
|
|
|
"""List library materials with their aliases."""
|
|
|
|
|
sql = """
|
|
|
|
|
SELECT m.id, m.name, m.schaeffler_code, m.description,
|
|
|
|
|
SELECT m.id, m.name, m.hartomat_code, m.description,
|
|
|
|
|
COALESCE(
|
|
|
|
|
(SELECT json_agg(ma.alias) FROM material_aliases ma WHERE ma.material_id = m.id),
|
|
|
|
|
'[]'::json
|
|
|
|
|
) AS aliases
|
|
|
|
|
FROM materials m
|
|
|
|
|
WHERE m.schaeffler_code IS NOT NULL
|
|
|
|
|
WHERE m.hartomat_code IS NOT NULL
|
|
|
|
|
"""
|
|
|
|
|
params: dict = {}
|
|
|
|
|
if query:
|
|
|
|
@@ -698,7 +698,7 @@ async def _tool_list_materials(db: AsyncSession, tenant_id: str, query: str = ""
|
|
|
|
|
aliases = r["aliases"] if isinstance(r["aliases"], list) else []
|
|
|
|
|
materials.append({
|
|
|
|
|
"name": r["name"],
|
|
|
|
|
"schaeffler_code": r["schaeffler_code"],
|
|
|
|
|
"hartomat_code": r["hartomat_code"],
|
|
|
|
|
"description": r["description"],
|
|
|
|
|
"aliases": aliases[:10], # cap to avoid token bloat
|
|
|
|
|
})
|
|
|
|
|