mcikalmerdeka's picture
refactor application structure and enhance logging capabilities
9d5041f
Raw
History Blame Contribute Delete
5.98 kB
"""Main agent implementation"""
from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
from .visualizer import ContextVisualizer
from .memory import ConversationMemory
from .knowledge import KnowledgeBase
from .tools import calculate_metric, get_current_time
from config.settings import Settings
from config import logger_agent, logger_memory, logger_knowledge
class ContextEngineeringAgent:
"""
Agent that demonstrates context engineering principles:
- Relevance: Only includes needed context
- Structure: Clear separation of context layers
- Timing: Retrieves information when needed
- Consistency: Stable system instructions
"""
def __init__(self):
logger_agent.info("Initializing ContextEngineeringAgent")
# Initialize components
logger_agent.debug(f"Initializing LLM with model: {Settings.MODEL_NAME}")
self.llm = ChatOpenAI(
model=Settings.MODEL_NAME,
temperature=Settings.TEMPERATURE
)
logger_agent.info("Loading knowledge base from FAISS index")
self.knowledge_base = KnowledgeBase(
pdf_path=Settings.PDF_PATH,
index_path=Settings.FAISS_INDEX_PATH,
embedding_model=Settings.EMBEDDING_MODEL,
top_k=Settings.RAG_TOP_K,
recreate_index=False # Load existing index by default
)
logger_agent.debug(f"Initializing conversation memory (max_messages={Settings.MAX_CONVERSATION_MESSAGES})")
self.memory = ConversationMemory(max_messages=Settings.MAX_CONVERSATION_MESSAGES)
self.visualizer = ContextVisualizer()
# System instructions
self.system_prompt = Settings.SYSTEM_PROMPT
# Create tools
self.tools = [calculate_metric, get_current_time]
logger_agent.debug(f"Created {len(self.tools)} tools: {[t.name for t in self.tools]}")
# Create agent
logger_agent.info("Creating LangChain agent with system prompt and tools")
self.agent = create_agent(
model=self.llm,
tools=self.tools,
system_prompt=self.system_prompt
)
logger_agent.info("ContextEngineeringAgent initialized successfully")
def process_query(self, user_query: str) -> tuple[str, ContextVisualizer]:
"""
Process a user query with full context engineering
Returns: (response, visualizer)
"""
logger_agent.info(f"Processing query: {user_query[:50]}..." if len(user_query) > 50 else f"Processing query: {user_query}")
# Reset visualizer for new query
self.visualizer = ContextVisualizer()
# Layer 1: System Instructions
logger_agent.debug("Adding layer: System Instructions")
self.visualizer.add_layer(
"System Instructions",
self.system_prompt,
)
# Layer 2: Conversation History
logger_memory.debug("Retrieving conversation history")
history_text = self.memory.get_history_text()
logger_agent.debug(f"Conversation history length: {len(history_text)} characters")
self.visualizer.add_layer(
"Conversation History",
history_text if history_text != "No previous conversation" else "No previous conversation",
)
# Layer 3: Retrieved Knowledge (RAG)
logger_knowledge.info(f"Retrieving relevant documents for query")
retrieved_context = self.knowledge_base.retrieve_relevant(user_query)
doc_count = len([c for c in retrieved_context.split("--- Chunk") if c.strip()])
logger_knowledge.info(f"Retrieved {doc_count} document chunks")
logger_agent.debug(f"Retrieved context length: {len(retrieved_context)} characters")
self.visualizer.add_layer(
"Retrieved Knowledge (RAG)",
retrieved_context,
)
# Layer 4: Current User Query
logger_agent.debug("Adding layer: User Query")
self.visualizer.add_layer(
"User Query",
user_query,
)
# Layer 5: Available Tools
logger_agent.debug("Adding layer: Available Tools")
tools_context = "\n".join([
f"- {tool.name}: {tool.description}" for tool in self.tools
])
self.visualizer.add_layer(
"Available Tools",
tools_context,
)
# Build the context structure
total_tokens = sum(self.visualizer.token_counts.values())
logger_agent.info(f"Total context size: {total_tokens} tokens across {len(self.visualizer.context_layers)} layers")
context_message = f"""Context from Knowledge Base:
{retrieved_context}
Previous Conversation:
{history_text}
Current Question:
{user_query}"""
# Invoke agent
logger_agent.info("Invoking LangChain agent with assembled context")
try:
result = self.agent.invoke({
"messages": [{"role": "user", "content": context_message}]
})
logger_agent.info("Agent invocation successful")
except Exception as e:
logger_agent.error(f"Agent invocation failed: {str(e)}")
raise
# Extract response
response = result["messages"][-1].content
response_preview = response[:100] + "..." if len(response) > 100 else response
logger_agent.info(f"Generated response: {response_preview}")
# Update conversation memory
logger_memory.info("Adding user message to conversation memory")
self.memory.add_user_message(user_query)
logger_memory.info("Adding AI response to conversation memory")
self.memory.add_ai_message(response)
logger_agent.info("Query processing completed successfully")
return response, self.visualizer