참고소스 수정본
This commit is contained in:
404
참고/ontocast-main/ontocast/onto/context.py
Normal file
404
참고/ontocast-main/ontocast/onto/context.py
Normal file
@@ -0,0 +1,404 @@
|
||||
"""Context passing system for agent-based workflow.
|
||||
|
||||
This module provides functionality for passing context between agents,
|
||||
enabling memory and incremental processing.
|
||||
"""
|
||||
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from enum import StrEnum
|
||||
from typing import Any
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from ontocast.onto.sparql_models import SPARQLOperationModel
|
||||
from ontocast.tool.graph_version_manager import GraphVersion
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
summary_template = """
|
||||
ONTOLOGY CONTEXT:
|
||||
{ontology_context}
|
||||
|
||||
FACTS CONTEXT:
|
||||
{facts_context}
|
||||
|
||||
CONTEXT METADATA:
|
||||
- Agent type: `{agent_type}`
|
||||
- Timestamp: {context_timestamp}
|
||||
- Additional metadata: {context_metadata}
|
||||
"""
|
||||
|
||||
|
||||
class AgentType(StrEnum):
|
||||
"""Enumeration of agent types for type safety."""
|
||||
|
||||
RENDERER_FACTS = "renderer_facts"
|
||||
RENDERER_ONTOLOGY = "renderer_ontology"
|
||||
CRITIC_FACTS = "critic_facts"
|
||||
CRITIC_ONTOLOGY = "critic_ontology"
|
||||
AGGREGATOR = "aggregator"
|
||||
CONVERTER = "converter"
|
||||
CHUNKER = "chunker"
|
||||
|
||||
|
||||
class Role(StrEnum):
|
||||
"""Enumeration of conversation roles for type safety."""
|
||||
|
||||
SYSTEM = "system"
|
||||
USER = "user"
|
||||
ASSISTANT = "assistant"
|
||||
|
||||
|
||||
class AgentContext(BaseModel):
|
||||
"""Context information passed between agents.
|
||||
|
||||
This class encapsulates all the context information that agents
|
||||
need to build upon previous work rather than starting fresh.
|
||||
"""
|
||||
|
||||
# Agent identification
|
||||
agent_type: AgentType = Field(description="Type of agent for type safety")
|
||||
|
||||
# Previous work context
|
||||
previous_ontology_version: GraphVersion | None = Field(
|
||||
default=None, description="Previous ontology version if available"
|
||||
)
|
||||
previous_facts_version: GraphVersion | None = Field(
|
||||
default=None, description="Previous facts version if available"
|
||||
)
|
||||
|
||||
# Previous operations (append-only for performance)
|
||||
previous_ontology_operations: list[SPARQLOperationModel] = Field(
|
||||
default_factory=list, description="Previous ontology SPARQL operations"
|
||||
)
|
||||
previous_facts_operations: list[SPARQLOperationModel] = Field(
|
||||
default_factory=list, description="Previous facts SPARQL operations"
|
||||
)
|
||||
|
||||
# Previous critiques (append-only for consistency)
|
||||
previous_ontology_critique: dict[str, Any] | None = Field(
|
||||
default=None, description="Previous ontology critique if available"
|
||||
)
|
||||
previous_facts_critique: dict[str, Any] | None = Field(
|
||||
default=None, description="Previous facts critique if available"
|
||||
)
|
||||
|
||||
# Context metadata (append-only strategy)
|
||||
context_timestamp: datetime = Field(
|
||||
default_factory=datetime.now, description="When this context was created"
|
||||
)
|
||||
context_metadata: dict[str, Any] = Field(
|
||||
default_factory=dict, description="Additional context metadata"
|
||||
)
|
||||
|
||||
# Conversation memory for LLM calls
|
||||
conversation_memory: list[dict[str, Any]] = Field(
|
||||
default_factory=list, description="Conversation history for LLM context"
|
||||
)
|
||||
|
||||
# Dynamic context construction
|
||||
dynamic_context: dict[str, Any] = Field(
|
||||
default_factory=dict,
|
||||
description="Dynamically constructed context for current interaction",
|
||||
)
|
||||
|
||||
def get_ontology_context_summary(self) -> str:
|
||||
"""Get a summary of ontology context for prompts."""
|
||||
if not self.previous_ontology_version:
|
||||
return "No previous ontology context available."
|
||||
|
||||
summary = f"Previous ontology version: {self.previous_ontology_version.id}\n"
|
||||
summary += f"Previous ontology size: {self.previous_ontology_version.get_size()} triples\n"
|
||||
summary += f"Previous ontology operations: {len(self.previous_ontology_operations)} SPARQL operations\n"
|
||||
|
||||
if self.previous_ontology_critique:
|
||||
summary += f"Previous ontology critique score: {self.previous_ontology_critique.get('score', 'N/A')}\n"
|
||||
summary += f"Previous ontology critique issues: {self.previous_ontology_critique.get('issues', 'None')}\n"
|
||||
|
||||
return summary
|
||||
|
||||
def get_facts_context_summary(self) -> str:
|
||||
"""Get a summary of facts context for prompts."""
|
||||
if not self.previous_facts_version:
|
||||
return "No previous facts context available."
|
||||
|
||||
summary = f"Previous facts version: {self.previous_facts_version.id}\n"
|
||||
summary += (
|
||||
f"Previous facts size: {self.previous_facts_version.get_size()} triples\n"
|
||||
)
|
||||
summary += f"Previous facts operations: {len(self.previous_facts_operations)} SPARQL operations\n"
|
||||
|
||||
if self.previous_facts_critique:
|
||||
summary += f"Previous facts critique score: {self.previous_facts_critique.get('score', 'N/A')}\n"
|
||||
summary += f"Previous facts critique issues: {self.previous_facts_critique.get('issues', 'None')}\n"
|
||||
|
||||
return summary
|
||||
|
||||
def get_full_context_summary(self) -> str:
|
||||
"""Get a complete context summary for prompts."""
|
||||
ontology_context = self.get_ontology_context_summary()
|
||||
facts_context = self.get_facts_context_summary()
|
||||
|
||||
summary = summary_template.format(
|
||||
facts_context=facts_context,
|
||||
ontology_context=ontology_context,
|
||||
agent_type=self.agent_type.value,
|
||||
context_timestamp=self.context_timestamp.isoformat(),
|
||||
context_metadata=self.context_metadata,
|
||||
)
|
||||
|
||||
return summary
|
||||
|
||||
def add_conversation_memory(
|
||||
self, role: Role, content: str, metadata: dict[str, Any] | None = None
|
||||
) -> None:
|
||||
"""Add a conversation entry to memory (append-only strategy).
|
||||
|
||||
Args:
|
||||
role: Role of the speaker (Role.SYSTEM, Role.USER, Role.ASSISTANT)
|
||||
content: Content of the message
|
||||
metadata: Optional metadata for the conversation entry
|
||||
"""
|
||||
entry = {
|
||||
"role": role.value,
|
||||
"content": content,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"metadata": metadata or {},
|
||||
}
|
||||
self.conversation_memory.append(entry)
|
||||
logger.debug(f"Added conversation memory for {self.agent_type}: {role.value}")
|
||||
|
||||
def get_conversation_context(self, max_entries: int = 10) -> str:
|
||||
"""Get conversation context for LLM calls.
|
||||
|
||||
Args:
|
||||
max_entries: Maximum number of conversation entries to include
|
||||
|
||||
Returns:
|
||||
str: Formatted conversation context
|
||||
"""
|
||||
if not self.conversation_memory:
|
||||
return "No conversation history available."
|
||||
|
||||
# Get the most recent entries (append-only strategy preserves order)
|
||||
recent_entries = self.conversation_memory[-max_entries:]
|
||||
|
||||
context = "CONVERSATION HISTORY:\n"
|
||||
for entry in recent_entries:
|
||||
context += f"{entry['role'].upper()}: {entry['content']}\n"
|
||||
if entry.get("metadata"):
|
||||
context += f" Metadata: {entry['metadata']}\n"
|
||||
context += "\n"
|
||||
|
||||
return context
|
||||
|
||||
def build_dynamic_context(self, interaction_type: str, **kwargs) -> dict[str, Any]:
|
||||
"""Build dynamic context for current interaction.
|
||||
|
||||
Args:
|
||||
interaction_type: Type of interaction (render, critique, etc.)
|
||||
**kwargs: Additional context parameters
|
||||
|
||||
Returns:
|
||||
dict[str, Any]: Dynamic context for the interaction
|
||||
"""
|
||||
dynamic_context = {
|
||||
"interaction_type": interaction_type,
|
||||
"timestamp": datetime.now().isoformat(),
|
||||
"agent_type": self.agent_type,
|
||||
"context_summary": self.get_full_context_summary(),
|
||||
"conversation_context": self.get_conversation_context(),
|
||||
**kwargs,
|
||||
}
|
||||
|
||||
# Update the dynamic context
|
||||
self.dynamic_context.update(dynamic_context)
|
||||
|
||||
return dynamic_context
|
||||
|
||||
def get_llm_context(self) -> str:
|
||||
"""Get complete context for LLM calls including conversation memory.
|
||||
|
||||
Returns:
|
||||
str: Complete context for LLM calls
|
||||
"""
|
||||
|
||||
return (
|
||||
f"{self.get_full_context_summary()}\n\n"
|
||||
f"{self.get_conversation_context()}\n\n"
|
||||
f"DYNAMIC CONTEXT:\n{self.dynamic_context}"
|
||||
)
|
||||
|
||||
|
||||
class ContextManager(BaseModel):
|
||||
"""Manages context passing between agents.
|
||||
|
||||
This class handles the creation, storage, and retrieval of context
|
||||
information for agent-based workflows.
|
||||
"""
|
||||
|
||||
context_history: list[AgentContext] = Field(
|
||||
default_factory=list, description="History of agent contexts"
|
||||
)
|
||||
current_context: AgentContext | None = Field(
|
||||
default=None, description="Current active context"
|
||||
)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
"""Initialize the context manager."""
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def create_context(
|
||||
self,
|
||||
agent_type: AgentType,
|
||||
previous_ontology_version: GraphVersion | None = None,
|
||||
previous_facts_version: GraphVersion | None = None,
|
||||
previous_ontology_operations: list[SPARQLOperationModel] | None = None,
|
||||
previous_facts_operations: list[SPARQLOperationModel] | None = None,
|
||||
previous_ontology_critique: dict[str, Any] | None = None,
|
||||
previous_facts_critique: dict[str, Any] | None = None,
|
||||
metadata: dict[str, Any] | None = None,
|
||||
) -> AgentContext:
|
||||
"""Create a new context for an agent.
|
||||
|
||||
Args:
|
||||
agent_type: Name of the agent creating the context.
|
||||
agent_type: Type of agent (renderer, critic, etc.).
|
||||
previous_ontology_version: Previous ontology version if available.
|
||||
previous_facts_version: Previous facts version if available.
|
||||
previous_ontology_operations: Previous ontology operations if available.
|
||||
previous_facts_operations: Previous facts operations if available.
|
||||
previous_ontology_critique: Previous ontology critique if available.
|
||||
previous_facts_critique: Previous facts critique if available.
|
||||
metadata: Additional metadata for the context.
|
||||
|
||||
Returns:
|
||||
AgentContext: The created context.
|
||||
"""
|
||||
context = AgentContext(
|
||||
agent_type=agent_type,
|
||||
previous_ontology_version=previous_ontology_version,
|
||||
previous_facts_version=previous_facts_version,
|
||||
previous_ontology_operations=previous_ontology_operations or [],
|
||||
previous_facts_operations=previous_facts_operations or [],
|
||||
previous_ontology_critique=previous_ontology_critique,
|
||||
previous_facts_critique=previous_facts_critique,
|
||||
context_metadata=metadata or {},
|
||||
)
|
||||
|
||||
self.context_history.append(context)
|
||||
self.current_context = context
|
||||
|
||||
logger.info(f"Created context for {agent_type} ({agent_type})")
|
||||
return context
|
||||
|
||||
def get_current_context(self) -> AgentContext | None:
|
||||
"""Get the current context.
|
||||
|
||||
Returns:
|
||||
AgentContext | None: The current context, or None if not set.
|
||||
"""
|
||||
return self.current_context
|
||||
|
||||
def get_context_history(self) -> list[AgentContext]:
|
||||
"""Get the full context history.
|
||||
|
||||
Returns:
|
||||
list[AgentContext]: The complete context history.
|
||||
"""
|
||||
return self.context_history
|
||||
|
||||
def get_context_by_agent(self, agent_type: AgentType) -> list[AgentContext]:
|
||||
"""Get context history for a specific agent.
|
||||
|
||||
Args:
|
||||
agent_type: Name of the agent to get context for.
|
||||
|
||||
Returns:
|
||||
list[AgentContext]: Context history for the specified agent.
|
||||
"""
|
||||
return [ctx for ctx in self.context_history if ctx.agent_type == agent_type]
|
||||
|
||||
def get_latest_context_by_agent(self, agent_type: AgentType) -> AgentContext | None:
|
||||
"""Get the latest context for a specific agent.
|
||||
|
||||
Args:
|
||||
agent_type: Name of the agent to get latest context for.
|
||||
|
||||
Returns:
|
||||
AgentContext | None: The latest context for the specified agent, or None.
|
||||
"""
|
||||
agent_contexts = self.get_context_by_agent(agent_type)
|
||||
return agent_contexts[-1] if agent_contexts else None
|
||||
|
||||
def update_context(
|
||||
self,
|
||||
agent_type: AgentType,
|
||||
ontology_version: GraphVersion | None = None,
|
||||
facts_version: GraphVersion | None = None,
|
||||
ontology_operations: list[SPARQLOperationModel] | None = None,
|
||||
facts_operations: list[SPARQLOperationModel] | None = None,
|
||||
ontology_critique: dict[str, Any] | None = None,
|
||||
facts_critique: dict[str, Any] | None = None,
|
||||
metadata: dict[str, Any] | None = None,
|
||||
) -> AgentContext:
|
||||
"""Update the current context with new information.
|
||||
|
||||
Args:
|
||||
agent_type: Name of the agent updating the context.
|
||||
ontology_version: New ontology version if available.
|
||||
facts_version: New facts version if available.
|
||||
ontology_operations: New ontology operations if available.
|
||||
facts_operations: New facts operations if available.
|
||||
ontology_critique: New ontology critique if available.
|
||||
facts_critique: New facts critique if available.
|
||||
metadata: Additional metadata for the context.
|
||||
|
||||
Returns:
|
||||
AgentContext: The updated context.
|
||||
"""
|
||||
if not self.current_context:
|
||||
# Create new context if none exists
|
||||
return self.create_context(
|
||||
agent_type=agent_type,
|
||||
previous_ontology_version=ontology_version,
|
||||
previous_facts_version=facts_version,
|
||||
previous_ontology_operations=ontology_operations,
|
||||
previous_facts_operations=facts_operations,
|
||||
previous_ontology_critique=ontology_critique,
|
||||
previous_facts_critique=facts_critique,
|
||||
metadata=metadata,
|
||||
)
|
||||
|
||||
# Update existing context
|
||||
if ontology_version:
|
||||
self.current_context.previous_ontology_version = ontology_version
|
||||
if facts_version:
|
||||
self.current_context.previous_facts_version = facts_version
|
||||
if ontology_operations:
|
||||
self.current_context.previous_ontology_operations = ontology_operations
|
||||
if facts_operations:
|
||||
self.current_context.previous_facts_operations = facts_operations
|
||||
if ontology_critique:
|
||||
self.current_context.previous_ontology_critique = ontology_critique
|
||||
if facts_critique:
|
||||
self.current_context.previous_facts_critique = facts_critique
|
||||
if metadata:
|
||||
self.current_context.context_metadata.update(metadata)
|
||||
|
||||
self.current_context.context_timestamp = datetime.now()
|
||||
|
||||
logger.info(f"Updated context for {agent_type}")
|
||||
return self.current_context
|
||||
|
||||
def clear_context(self):
|
||||
"""Clear the current context."""
|
||||
self.current_context = None
|
||||
logger.info("Cleared current context")
|
||||
|
||||
def clear_history(self):
|
||||
"""Clear the entire context history."""
|
||||
self.context_history = []
|
||||
self.current_context = None
|
||||
logger.info("Cleared context history")
|
||||
Reference in New Issue
Block a user