Implement AI orchestration wedding demo
This commit is contained in:
3
backend/app/application/README.md
Normal file
3
backend/app/application/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Application
|
||||
|
||||
Application services coordinate transcript events, context, memory, planning, validation, policy checks, persistence, and event publication.
|
||||
1
backend/app/application/__init__.py
Normal file
1
backend/app/application/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Application services coordinating domain and infrastructure."""
|
||||
72
backend/app/application/orchestrator.py
Normal file
72
backend/app/application/orchestrator.py
Normal file
@@ -0,0 +1,72 @@
|
||||
from uuid import uuid4
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.ai.tool_registry import ToolRegistry
|
||||
from app.domain.schemas import EventType, PendingActionCreate, TranscriptChunk
|
||||
from app.infrastructure.database import PendingAction
|
||||
from app.infrastructure.events import EventPublisher
|
||||
from app.memory.context_builder import ContextBuilder
|
||||
from app.memory.memory_manager import MemoryManager
|
||||
from app.planner.llm_planner import HybridPlanner
|
||||
from app.validation.action_validator import ActionValidator
|
||||
from app.validation.policy_engine import PolicyEngine
|
||||
|
||||
|
||||
class Orchestrator:
|
||||
"""Turns transcript events into pending, validated review actions."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
context: ContextBuilder,
|
||||
memory: MemoryManager,
|
||||
planner: HybridPlanner,
|
||||
registry: ToolRegistry,
|
||||
publisher: EventPublisher,
|
||||
) -> None:
|
||||
self.context = context
|
||||
self.memory = memory
|
||||
self.planner = planner
|
||||
self.registry = registry
|
||||
self.publisher = publisher
|
||||
|
||||
async def ingest(self, session: Session, chunk: TranscriptChunk) -> PendingAction | None:
|
||||
request_id = str(uuid4())
|
||||
self.context.add_chunk(chunk)
|
||||
self.publisher.publish(EventType.CONVERSATION_EVENT, request_id, chunk.model_dump(mode="json"))
|
||||
memories = self.memory.retrieve(chunk.text)
|
||||
decision = await self.planner.plan(chunk, self.context.snapshot(), memories, self.registry.list())
|
||||
self.context.add_decision(decision.model_dump())
|
||||
|
||||
validation = ActionValidator(self.registry).validate(decision)
|
||||
existing = [row.payload for row in session.query(PendingAction).filter(PendingAction.status == "pending_review").all()]
|
||||
policy = PolicyEngine(existing).evaluate(decision)
|
||||
if not validation.valid or not policy.allowed:
|
||||
self.publisher.publish(
|
||||
EventType.ACTION_REJECTED,
|
||||
request_id,
|
||||
{"decision": decision.model_dump(), "validation": validation.model_dump(), "policy": policy.model_dump()},
|
||||
)
|
||||
return None
|
||||
action_in = PendingActionCreate(
|
||||
meeting_id="demo-meeting",
|
||||
tool=decision.tool or "",
|
||||
intent=decision.intent,
|
||||
reasoning=decision.reasoning,
|
||||
confidence=decision.confidence,
|
||||
payload=decision.arguments,
|
||||
extracted_entities=decision.extracted_entities,
|
||||
validation=validation,
|
||||
policy=policy,
|
||||
)
|
||||
row = action_in.model_dump(mode="json")
|
||||
row["validation"] = validation.model_dump()
|
||||
row["policy"] = policy.model_dump()
|
||||
action = PendingAction(**row, status="pending_review")
|
||||
session.add(action)
|
||||
session.commit()
|
||||
session.refresh(action)
|
||||
self.memory.upsert("pending_action", f"{action.intent}: {action.payload}", {"action_id": action.id})
|
||||
self.publisher.publish(EventType.ACTION_CREATED, request_id, {"action_id": action.id, "decision": decision.model_dump()})
|
||||
self.publisher.publish(EventType.MEMORY_UPDATED, request_id, {"action_id": action.id, "type": "pending_action"})
|
||||
return action
|
||||
Reference in New Issue
Block a user