agent.py aktualisiert

This commit is contained in:
2026-07-04 21:56:31 +00:00
parent ec7bad6d1b
commit 01eddde642
+27 -75
View File
@@ -1,5 +1,4 @@
import json
import re
from config import OPENROUTER_MODEL
from openrouter_client import client
@@ -14,88 +13,43 @@ class Agent:
{
"role": "system",
"content": (
"Du bist N.O.R.A. ( Neural Operations for Residential Automation), ein Smart-Home Assistent. Du bist höfflich zielorientiert und leicht ironisch und zynisch. Du bevorzugst kurze präzise Antworten ausser du wirst nach langen Erkärungen gefragt. Du kontrolierst das Smart-Home und bist perönlicher Assistent\n"
"Du kannst MCP Tools verwenden.\n\n"
"Wenn du ein Tool benutzen willst, antworte STRICT als JSON:\n"
"{\n"
' "tool": "tool_name",\n'
' "args": {...}\n'
"}\n\n"
"Wenn kein Tool nötig ist:\n"
"{\n"
' "response": "Text"\n'
"}\n\n"
"WICHTIG:\n"
"- KEIN Markdown\n"
"- KEIN zusätzlicher Text\n"
"- NUR JSON\n"
"Du bist JARVIS, ein Smart-Home Assistent.\n"
"Du steuerst ein Haus über MCP Tools.\n"
"Antworte normal oder nutze Tools wenn nötig."
)
}
]
async def load_tools(self):
"""
MCP Tools holen und in OpenRouter Format konvertieren
"""
response = await self.mcp.list_tools()
res = await self.mcp.list_tools()
self.tools = []
for t in response.tools:
for t in res.tools:
self.tools.append({
"type": "function",
"function": {
"name": t.name,
"description": t.description,
"parameters": t.inputSchema,
"parameters": t.inputSchema
}
})
print(f"[JARVIS] {len(self.tools)} Tools geladen")
def _extract_json(self, text: str):
"""
Repariert kaputte LLM JSON Outputs
"""
try:
return json.loads(text)
except:
pass
# JSON aus Text extrahieren
match = re.search(r"\{.*\}", text, re.DOTALL)
if match:
try:
return json.loads(match.group(0))
except:
pass
return None
async def _execute_tool(self, tool_call):
"""
Führt MCP Tool aus
"""
name = tool_call["tool"]
args = tool_call.get("args", {})
async def _run_tool(self, tool_call):
name = tool_call.function.name
args = json.loads(tool_call.function.arguments or "{}")
result = await self.mcp.call_tool(name, args)
return result
async def run(self, user_input: str):
"""
Vollständiger Tool-Calling Loop
"""
self.messages.append({
"role": "user",
"content": user_input
})
MAX_STEPS = 8
for _ in range(MAX_STEPS):
for _ in range(8):
response = await client.chat.completions.create(
model=OPENROUTER_MODEL,
@@ -103,38 +57,36 @@ class Agent:
tools=self.tools
)
msg = response.choices[0].message.content
message = response.choices[0].message
parsed = self._extract_json(msg)
# 🧠 TOOL CALL PATH
if getattr(message, "tool_calls", None):
# ❌ Falls kein gültiges JSON → direkte Antwort
if not parsed:
return msg
self.messages.append(message)
# 🧠 Tool Call
if "tool" in parsed:
for tool_call in message.tool_calls:
tool_result = await self._execute_tool(parsed)
self.messages.append({
"role": "assistant",
"content": msg
})
result = await self._run_tool(tool_call)
self.messages.append({
"role": "tool",
"content": str(tool_result)
"tool_call_id": tool_call.id,
"content": str(result)
})
continue
# ✅ Final Response
if "response" in parsed:
# 🧠 NORMAL RESPONSE PATH
if message.content:
self.messages.append({
"role": "assistant",
"content": parsed["response"]
"content": message.content
})
return parsed["response"]
return message.content
return "⚠️ Tool Loop Limit erreicht"
# 🧠 SAFETY FALLBACK
return "Ich konnte keine gültige Antwort generieren."
return "Tool Loop Limit erreicht."