""" OpenAI Model Adapter. Provides OpenAI-specific context formatting using markdown which GPT models understand well. """ from typing import Any, ClassVar from ..types import BaseContext, ContextType from .base import ModelAdapter class OpenAIAdapter(ModelAdapter): """ OpenAI-specific context formatting adapter. GPT models work well with markdown formatting, so we use headers and structured markdown for clarity. Features: - Markdown headers for each context type - Bulleted lists for document sources - Bold role labels for conversations - Code blocks for tool outputs """ MODEL_PATTERNS: ClassVar[list[str]] = ["gpt", "openai", "o1", "o3"] def format( self, contexts: list[BaseContext], **kwargs: Any, ) -> str: """ Format contexts for OpenAI models. Uses markdown formatting for structured content. Args: contexts: List of contexts to format **kwargs: Additional formatting options Returns: Markdown-structured context string """ if not contexts: return "" by_type = self.group_by_type(contexts) parts: list[str] = [] for ct in self.get_type_order(): if ct in by_type: formatted = self.format_type(by_type[ct], ct, **kwargs) if formatted: parts.append(formatted) return self.get_separator().join(parts) def format_type( self, contexts: list[BaseContext], context_type: ContextType, **kwargs: Any, ) -> str: """ Format contexts of a specific type for OpenAI. Args: contexts: List of contexts of the same type context_type: The type of contexts **kwargs: Additional formatting options Returns: Markdown-formatted string for this context type """ if not contexts: return "" if context_type == ContextType.SYSTEM: return self._format_system(contexts) elif context_type == ContextType.TASK: return self._format_task(contexts) elif context_type == ContextType.KNOWLEDGE: return self._format_knowledge(contexts) elif context_type == ContextType.CONVERSATION: return self._format_conversation(contexts) elif context_type == ContextType.TOOL: return self._format_tool(contexts) return "\n".join(c.content for c in contexts) def _format_system(self, contexts: list[BaseContext]) -> str: """Format system contexts.""" content = "\n\n".join(c.content for c in contexts) return content def _format_task(self, contexts: list[BaseContext]) -> str: """Format task contexts.""" content = "\n\n".join(c.content for c in contexts) return f"## Current Task\n\n{content}" def _format_knowledge(self, contexts: list[BaseContext]) -> str: """ Format knowledge contexts as structured documents. Each knowledge context becomes a section with source attribution. """ parts = ["## Reference Documents\n"] for ctx in contexts: source = ctx.source score = ctx.metadata.get("score", ctx.metadata.get("relevance_score", "")) if score: parts.append(f"### Source: {source} (relevance: {score})\n") else: parts.append(f"### Source: {source}\n") parts.append(ctx.content) parts.append("") return "\n".join(parts) def _format_conversation(self, contexts: list[BaseContext]) -> str: """ Format conversation contexts as message history. Uses bold role labels for clear turn delineation. """ parts = [] for ctx in contexts: role = ctx.metadata.get("role", "user").upper() parts.append(f"**{role}**: {ctx.content}") return "\n\n".join(parts) def _format_tool(self, contexts: list[BaseContext]) -> str: """ Format tool contexts as tool results. Each tool result is in a code block with the tool name. """ parts = ["## Recent Tool Results\n"] for ctx in contexts: tool_name = ctx.metadata.get("tool_name", "unknown") status = ctx.metadata.get("status", "") if status: parts.append(f"### Tool: {tool_name} ({status})\n") else: parts.append(f"### Tool: {tool_name}\n") parts.append(f"```\n{ctx.content}\n```") parts.append("") return "\n".join(parts)