Kansho/backend/engine.py

58 lines
2.3 KiB
Python

"""Single prompt execution entry. Templates live in the DB; LLM egress only via Privacy Gateway."""
from __future__ import annotations
from typing import Any
import placeholder_system # noqa: F401 registers system keys
import privacy_placeholders
from entitlements import EntitlementError, check_feature_access
from placeholders import PlaceholderError, resolve_template
from privacy_gateway import GatewayRequest, PrivacyGatewayError, complete
class EngineError(Exception):
def __init__(self, code: str, message: str, status_code: int = 400):
super().__init__(message)
self.code = code
self.message = message
self.status_code = status_code
def preview_prompt(prompt: dict, context: dict[str, Any] | None = None) -> dict:
template = prompt.get("template") or ""
if prompt.get("prompt_type") != "base":
raise EngineError("prompt_type_not_ready", "Pipeline- und Workflow-Typen sind vorbereitet, aber noch ohne Executor-Stufen.")
try:
rendered = resolve_template(template, context or {})
privacy_tokens = privacy_placeholders.validate_tokens(template)
except PlaceholderError as exc:
raise EngineError(exc.code, exc.message) from exc
return {
"prompt_id": prompt["id"],
"slug": prompt["slug"],
"rendered": rendered,
"privacy_tokens": privacy_tokens,
"llm": False,
}
def execute_prompt(prompt: dict, profile_id: str, purpose: str, data_class: str, context: dict[str, Any] | None = None) -> dict:
preview = preview_prompt(prompt, context)
feature_id = prompt.get("required_feature") or "ai_calls"
try:
check_feature_access(profile_id, feature_id)
except EntitlementError as exc:
raise EngineError(exc.code, exc.message, exc.status_code) from exc
try:
complete(
GatewayRequest(
prompt_id=prompt["id"],
purpose=purpose,
data_class=data_class,
payload={"template_chars": len(preview["rendered"]), "privacy_tokens": preview["privacy_tokens"]},
)
)
except PrivacyGatewayError as exc:
raise EngineError(exc.code, exc.message, exc.status_code) from exc
raise EngineError("provider_missing", "Gateway erlaubte einen Aufruf ohne konfigurierten Provider", 500)