2025-04-13AI Technology

Supercharging Knowledge Access: Advanced RAG Techniques with LLaMA 3

This article explores combining LLaMA 3 with advanced Retrieval Augmented Generation (RAG) techniques, addressing semantic fragmentation and context loss in traditional RAG systems through innovative approaches like knowledge graph construction, community detection, and intelligent indexing to significantly enhance information retrieval capabilities.

Keywords: LLaMA, LLaMA 3, LLaMA 3, Advanced RAG, GraphRAG, Knowledge Graph, Entity Relationship Extraction, Intelligent Indexing, Information Retrieval, LLaMA Tutorial, AI Learning

Introduction

In today's data-driven landscape, organizations face a critical challenge: how to effectively harness their vast repositories of information to power intelligent systems. Traditional search mechanisms often fall short when dealing with complex queries that require contextual understanding and nuanced responses. This is where Retrieval Augmented Generation (RAG) has emerged as a transformative solution, particularly when combined with powerful language models like LLaMA 3.

Consider a healthcare provider with thousands of medical documents, research papers, and clinical guidelines. When a physician needs specific information about a rare condition's treatment protocol, traditional keyword searches might return dozens of partially-relevant documents, leaving the physician to sift through and synthesize information manually. An advanced RAG system powered by LLaMA 3 can instead understand the context of the query, retrieve the most relevant information across multiple documents, and generate a comprehensive, accurate response that directly addresses the physician's need.

This article explores how LLaMA 3 can enhance RAG systems beyond conventional implementations, addressing key challenges in document processing, knowledge structuring, and response generation. We'll examine architectural approaches, implementation details, and best practices to help you build more intelligent information retrieval systems.

Background & Challenges

The Evolution of RAG Systems

RAG combines two powerful capabilities: retrieval from external knowledge sources and text generation using large language models (LLMs). Its core innovation lies in bridging the gap between static knowledge bases and dynamic language generation, addressing limitations of both approaches used in isolation.

Traditional RAG implementations typically follow a straightforward process:

  1. Document splitting: Breaking documents into manageable chunks
  2. Embedding generation: Converting text chunks into vector representations
  3. Vector storage: Storing embeddings in a vector database
  4. Retrieval: Finding relevant chunks through vector similarity search
  5. Content generation: Using an LLM to generate responses based on retrieved content

While this approach represents a significant advancement over pure LLM generation or keyword-based retrieval alone, it faces several challenges:

Limitations of Traditional RAG

  1. Semantic fragmentation: Document chunking often breaks semantic relationships between different parts of a document, causing loss of context.
  2. Ambiguity issues: Vector search at the chunk level struggles with disambiguating terms that have multiple meanings depending on context.
  3. Lack of global knowledge: Chunk-based retrieval misses connections between concepts that appear in different documents or parts of documents.
  4. Information faithfulness: Generated content may diverge from or misrepresent the retrieved information.
  5. Content relevance: Responses may include information that is factually correct but irrelevant to the user's actual intent.

These challenges point to a fundamental limitation: conventional RAG systems lack true understanding of the knowledge structure they contain. They excel at retrieving text chunks that share semantic similarity with a query, but struggle to build holistic understanding across chunks or evaluate the quality of generated responses.

Core Concepts & Architecture

The LLaMA 3 Advantage

LLaMA 3 brings several key improvements to RAG implementations:

  1. Enhanced contextual understanding: Better grasp of nuanced meanings in both queries and documents
  2. Improved reasoning capabilities: Ability to make logical connections across information sources
  3. Stronger semantic representation: More effective vector embeddings for retrieval
  4. Self-evaluation: Capacity to assess and improve response quality

By leveraging these capabilities, we can design more sophisticated RAG architectures that go beyond the basic retrieval-then-generate pattern. Let's explore the key components of an advanced RAG system powered by LLaMA 3.

GraphRAG: Structuring Knowledge as Relationships

GraphRAG represents a significant advancement over traditional RAG implementations by incorporating structured knowledge representation. Instead of treating documents as collections of independent chunks, GraphRAG constructs a knowledge graph that captures entities and relationships.

The process involves several key steps:

  1. Entity and Relationship Extraction: LLaMA 3 analyzes documents to identify entities and their relationships, structured as triples (subject-predicate-object).

  2. Knowledge Graph Construction: These triples form a graph where nodes represent entities and edges represent relationships.

  3. Community Detection: Using clustering algorithms (like the Leiden algorithm), the system identifies communities of closely related concepts.

  4. Community Summarization: LLaMA 3 generates concise summaries for each community, capturing the essence of related concepts.

  5. Dual-path Search: When a query arrives, the system can perform both local search (focusing on specific entities) and global search (leveraging community summaries for broader context).

This approach addresses the limitations of traditional RAG by preserving semantic relationships and enabling both detailed local information retrieval and high-level conceptual understanding.

Intelligent Index Construction

Building an effective index is crucial for RAG performance. With LLaMA 3, we can move beyond simple text chunking to create more semantically meaningful indices.

Here's how LLaMA 3 enhances the indexing process:

python
# Example of LLaMA 3-powered triple extraction
from llama_index.core import PromptTemplate

triple_extraction_prompt = PromptTemplate(
    """
    -Goal-
    Given a text document, identify all entities and their relationships.

    -Steps-
    1. Identify all entities. For each entity, extract:
       - entity_name: Name of the entity, capitalized
       - entity_type: Type of the entity (Person, Organization, Concept, etc.)
       - entity_description: Comprehensive description of the entity

    2. From the identified entities, identify all pairs that are clearly related.
       For each pair, extract:
       - source_entity: name of the source entity
       - target_entity: name of the target entity
       - relationship_description: explanation of the relationship
       - relationship_strength: integer score from 1-10 indicating strength

    -Input Document-
    {text}
    
    -Output Format-
    Provide a JSON array of all entities and relationships.
    """
)

# This prompt would be sent to LLaMA 3 to extract structured information

By extracting structured information in this way, we build a richer representation of the document content that supports more sophisticated retrieval strategies.

Advanced Retrieval Strategies

With a knowledge graph in place, we can implement more sophisticated retrieval strategies:

  1. Entity-centric retrieval: For queries about specific entities, retrieve information directly connected to those entities in the graph.

  2. Path-based retrieval: For questions about relationships between entities, find paths that connect them in the graph.

  3. Community-based retrieval: For broader questions, identify relevant communities and retrieve their summarized information.

python
# Example of community-based retrieval
def retrieve_from_communities(query, communities, embeddings_model):
    # Convert query to embedding
    query_embedding = embeddings_model.embed_query(query)
    
    # Find most relevant communities by comparing with community summaries
    community_scores = []
    for community_id, summary in communities.items():
        summary_embedding = embeddings_model.embed_document(summary)
        similarity = cosine_similarity(query_embedding, summary_embedding)
        community_scores.append((community_id, similarity))
    
    # Return top communities
    top_communities = sorted(community_scores, key=lambda x: x[1], reverse=True)[:3]
    return [communities[community_id] for community_id, _ in top_communities]

Response Generation and Evaluation

LLaMA 3 can not only generate responses based on retrieved information but also evaluate their quality along multiple dimensions:

  1. Faithfulness: Does the response accurately represent the retrieved information?
  2. Relevance: Does the response address the user's query?
  3. Coherence: Is the response logically structured and easy to follow?
  4. Completeness: Does the response cover all relevant aspects of the query?

This self-evaluation capability enables continuous improvement of the system:

python
# Example of response evaluation with LLaMA 3
def evaluate_response(query, retrieved_content, generated_response):
    evaluation_prompt = f"""
    Evaluate the quality of the following response to a query:
    
    Query: {query}
    
    Retrieved Information:
    {retrieved_content}
    
    Generated Response:
    {generated_response}
    
    Please score the response on a scale of 1-10 for each criterion:
    1. Faithfulness: Does the response accurately represent the retrieved information?
    2. Relevance: Does the response directly address the query?
    3. Coherence: Is the response logically structured and easy to follow?
    4. Completeness: Does the response cover all relevant aspects?
    
    For each criterion, explain your reasoning.
    """
    
    evaluation_result = llm_model.generate(evaluation_prompt)
    return evaluation_result

Practical Implementation

Let's walk through a practical implementation of an advanced RAG system using LLaMA 3 and explore key components in detail.

System Architecture Overview

Our implementation consists of four main components:

  1. Document Processor: Handles document ingestion and preprocessing
  2. Knowledge Graph Builder: Constructs and maintains the knowledge graph
  3. Query Engine: Manages query processing and retrieval
  4. Response Generator: Generates and evaluates responses

Document Processing and Graph Construction

The first step is processing documents to extract entities and relationships:

python
from llama_index.llms.ollama import Ollama
from llama_index.core import PromptTemplate
import networkx as nx
import json

# Initialize LLaMA 3 model
llm = Ollama(model="llama3", temperature=0.1)

def process_document(document_text):
    # Split document into manageable chunks if needed
    chunks = split_into_chunks(document_text, chunk_size=2000, overlap=200)
    
    graph = nx.DiGraph()
    
    for chunk in chunks:
        # Extract triples from each chunk
        extraction_prompt = triple_extraction_prompt.format(text=chunk)
        result = llm.complete(extraction_prompt)
        
        try:
            # Parse extracted information
            extracted_data = json.loads(result.text)
            
            # Add entities and relationships to graph
            for item in extracted_data:
                if "entity" in item:
                    # Add entity node
                    entity_name = item["entity_name"]
                    graph.add_node(
                        entity_name, 
                        type=item["entity_type"],
                        description=item["entity_description"]
                    )
                elif "relationship" in item:
                    # Add relationship edge
                    source = item["source_entity"]
                    target = item["target_entity"]
                    graph.add_edge(
                        source, 
                        target, 
                        description=item["relationship_description"],
                        strength=item["relationship_strength"]
                    )
        except json.JSONDecodeError:
            print(f"Failed to parse extraction result: {result.text}")
    
    return graph

Community Detection and Summarization

After building the knowledge graph, we need to identify communities of related concepts and generate summaries for each:

python
from community import best_partition
from collections import defaultdict

def detect_communities(graph):
    # Use Louvain algorithm for community detection
    partition = best_partition(graph)
    
    # Group nodes by community
    communities = defaultdict(list)
    for node, community_id in partition.items():
        communities[community_id].append(node)
    
    return communities

def generate_community_summaries(graph, communities, llm):
    summaries = {}
    
    for community_id, nodes in communities.items():
        # Extract all relevant information for this community
        community_info = []
        for node in nodes:
            node_data = graph.nodes[node]
            community_info.append(f"Entity: {node} ({node_data.get('type', 'Unknown')})")
            community_info.append(f"Description: {node_data.get('description', 'No description')}")
            
            # Add relationships within the community
            for neighbor in graph.neighbors(node):
                if neighbor in nodes:  # Only include relationships within the community
                    edge_data = graph.edges[node, neighbor]
                    community_info.append(
                        f"Relationship: {node} -> {neighbor}: {edge_data.get('description', 'No description')}"
                    )
        
        # Generate summary with LLaMA 3
        summary_prompt = f"""
        Summarize the main concepts and relationships in this knowledge community:
        
        {chr(10).join(community_info)}
        
        Provide a concise summary (150-200 words) that captures the key entities and their relationships.
        """
        
        summary_result = llm.complete(summary_prompt)
        summaries[community_id] = summary_result.text
    
    return summaries

Query Processing and Response Generation

When a query arrives, we need to process it and retrieve relevant information:

python
def process_query(query, graph, community_summaries, embeddings_model, llm):
    # Analyze query to determine if it's specific or broad
    analysis_prompt = f"""
    Analyze the following query and classify it as either:
    1. Specific - focused on a particular entity or relationship
    2. Broad - requiring general knowledge across multiple topics
    
    Query: {query}
    
    Output only "specific" or "broad".
    """
    
    analysis_result = llm.complete(analysis_prompt)
    query_type = analysis_result.text.strip().lower()
    
    # Retrieve information based on query type
    if "specific" in query_type:
        entities = extract_entities_from_query(query)
        retrieved_info = retrieve_entity_information(entities, graph)
    else:
        retrieved_info = retrieve_from_communities(query, community_summaries, embeddings_model)
    
    # Generate response
    response_prompt = f"""
    Answer the following question based on the retrieved information:
    
    Question: {query}
    
    Retrieved Information:
    {retrieved_info}
    
    Provide a comprehensive and accurate answer that directly addresses the question.
    If the retrieved information is insufficient, say so and provide the best answer possible.
    """
    
    response = llm.complete(response_prompt)
    
    # Evaluate response quality
    evaluation = evaluate_response(query, retrieved_info, response.text)
    
    return {
        "response": response.text,
        "retrieved_info": retrieved_info,
        "query_type": query_type
    }

Complete End-to-End Implementation Example

Let's put everything together with a complete, runnable example that demonstrates the power of GraphRAG with LLaMA 3:

python
from llama_index.llms.ollama import Ollama
from llama_index.core import PromptTemplate, SimpleDirectoryReader
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
import networkx as nx
import json
from community import best_partition
from collections import defaultdict
import os

# Initialize models
llm = Ollama(model="llama3", temperature=0.1)
embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")

# Triple extraction prompt
triple_extraction_prompt = PromptTemplate(
    """
    -Goal-
    Given a text document, identify all entities and their relationships.

    -Steps-
    1. Identify all entities. For each entity, extract:
       - entity_name: Name of the entity, capitalized
       - entity_type: Type of the entity (Person, Organization, Concept, etc.)
       - entity_description: Comprehensive description of the entity

    2. From the identified entities, identify all pairs that are clearly related.
       For each pair, extract:
       - source_entity: name of the source entity
       - target_entity: name of the target entity
       - relationship_description: explanation of the relationship
       - relationship_strength: integer score from 1-10 indicating strength

    -Input Document-
    {text}
    
    -Output Format-
    Provide a JSON array of all entities and relationships.
    """
)

def split_into_chunks(text, chunk_size=2000, overlap=200):
    """Split text into overlapping chunks."""
    chunks = []
    for i in range(0, len(text), chunk_size - overlap):
        chunks.append(text[i:i + chunk_size])
        if i + chunk_size >= len(text):
            break
    return chunks

def process_document(document_text):
    """Process document and extract knowledge graph."""
    chunks = split_into_chunks(document_text)
    graph = nx.DiGraph()
    
    for chunk in chunks:
        extraction_prompt = triple_extraction_prompt.format(text=chunk)
        result = llm.complete(extraction_prompt)
        
        try:
            # Parse result as JSON - this is simplified and would need error handling
            extracted_data = json.loads(result.text)
            
            for item in extracted_data:
                if "entity_name" in item:
                    # Add entity node
                    graph.add_node(
                        item["entity_name"], 
                        type=item.get("entity_type", "Unknown"),
                        description=item.get("entity_description", "")
                    )
                elif "source_entity" in item:
                    # Add relationship edge
                    graph.add_edge(
                        item["source_entity"], 
                        item["target_entity"],
                        description=item.get("relationship_description", ""),
                        strength=item.get("relationship_strength", 5)
                    )
        except json.JSONDecodeError:
            print(f"Failed to parse chunk result")
            continue
    
    return graph

def detect_communities(graph):
    """Detect communities in the knowledge graph."""
    partition = best_partition(graph)
    communities = defaultdict(list)
    for node, community_id in partition.items():
        communities[community_id].append(node)
    return communities

def generate_community_summaries(graph, communities):
    """Generate summaries for each community."""
    summaries = {}
    
    for community_id, nodes in communities.items():
        if not nodes:
            continue
            
        community_info = []
        for node in nodes:
            if node not in graph.nodes:
                continue
                
            node_data = graph.nodes[node]
            community_info.append(f"Entity: {node} ({node_data.get('type', 'Unknown')})")
            community_info.append(f"Description: {node_data.get('description', 'No description')}")
            
        summary_prompt = f"""
        Summarize the main concepts in this knowledge community:
        
        {chr(10).join(community_info)}
        
        Provide a concise summary (100-150 words) that captures the key entities.
        """
        
        summary_result = llm.complete(summary_prompt)
        summaries[community_id] = summary_result.text
    
    return summaries

def extract_entities_from_query(query):
    """Extract potential entities from the query."""
    entity_prompt = f"""
    Identify all potential entities in the following query:
    
    Query: {query}
    
    List only the entity names, one per line.
    """
    
    entity_result = llm.complete(entity_prompt)
    entities = [e.strip() for e in entity_result.text.split("\n") if e.strip()]
    return entities

def retrieve_entity_information(entities, graph):
    """Retrieve information about specific entities from the graph."""
    retrieved_info = []
    
    for entity in entities:
        # Find closest node if exact match not found
        if entity not in graph.nodes:
            continue
            
        # Get entity information
        node_data = graph.nodes[entity]
        retrieved_info.append(f"Entity: {entity} ({node_data.get('type', 'Unknown')})")
        retrieved_info.append(f"Description: {node_data.get('description', 'No description')}")
        
        # Get relationships
        for neighbor in graph.neighbors(entity):
            edge_data = graph.edges[entity, neighbor]
            retrieved_info.append(
                f"Relationship: {entity} -> {neighbor}: {edge_data.get('description', 'No description')}"
            )
    
    return "\n".join(retrieved_info)

def retrieve_from_communities(query, community_summaries, embed_model):
    """Retrieve information from community summaries."""
    if not community_summaries:
        return "No community information available."
        
    # Convert query to embedding
    query_embedding = embed_model.get_text_embedding(query)
    
    # Find most relevant communities
    community_scores = []
    for community_id, summary in community_summaries.items():
        summary_embedding = embed_model.get_text_embedding(summary)
        
        # Compute cosine similarity
        similarity = sum(a*b for a, b in zip(query_embedding, summary_embedding))
        similarity = similarity / (sum(a*a for a in query_embedding)**0.5 * sum(b*b for b in summary_embedding)**0.5)
        
        community_scores.append((community_id, similarity))
    
    # Get top communities
    top_communities = sorted(community_scores, key=lambda x: x[1], reverse=True)[:3]
    
    # Return community summaries
    result = []
    for community_id, score in top_communities:
        result.append(f"--- Community {community_id} (Relevance: {score:.2f}) ---")
        result.append(community_summaries[community_id])
        result.append("")
    
    return "\n".join(result)

def process_query(query, graph, community_summaries):
    """Process a user query and generate a response."""
    # Analyze query to determine if it's specific or broad
    analysis_prompt = f"""
    Analyze the following query and classify it as either:
    1. Specific - focused on a particular entity or relationship
    2. Broad - requiring general knowledge across multiple topics
    
    Query: {query}
    
    Output only "specific" or "broad".
    """
    
    analysis_result = llm.complete(analysis_prompt)
    query_type = analysis_result.text.strip().lower()
    
    # Retrieve information based on query type
    if "specific" in query_type:
        entities = extract_entities_from_query(query)
        retrieved_info = retrieve_entity_information(entities, graph)
    else:
        retrieved_info = retrieve_from_communities(query, community_summaries, embed_model)
    
    # Generate response
    response_prompt = f"""
    Answer the following question based on the retrieved information:
    
    Question: {query}
    
    Retrieved Information:
    {retrieved_info}
    
    Provide a comprehensive and accurate answer that directly addresses the question.
    If the retrieved information is insufficient, say so and provide the best answer possible.
    """
    
    response = llm.complete(response_prompt)
    
    return {
        "response": response.text,
        "retrieved_info": retrieved_info,
        "query_type": query_type
    }

# Main function to demonstrate the system
def main():
    # Load documents
    documents_dir = "./data"
    if not os.path.exists(documents_dir):
        os.makedirs(documents_dir)
        with open(os.path.join(documents_dir, "sample.txt"), "w") as f:
            f.write("""
            Kubernetes is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications. 
            It was originally developed by Google and is now maintained by the Cloud Native Computing Foundation (CNCF).
            Kubernetes clusters consist of a control plane and worker nodes. The control plane includes components like the API server, scheduler, and controller manager.
            Docker is a platform that uses containerization technology to create and run containers. Kubernetes can use Docker as one of its container runtimes.
            Microservices architecture is an approach to developing applications as a collection of small, independently deployable services.
            Many organizations use Kubernetes to manage their microservices-based applications in production environments.
            """)
    
    # Read documents
    documents = SimpleDirectoryReader(documents_dir).load_data()
    
    # Process documents
    print("Building knowledge graph...")
    graph = process_document(documents[0].text)
    
    # Detect communities
    print("Detecting communities...")
    communities = detect_communities(graph)
    
    # Generate community summaries
    print("Generating community summaries...")
    community_summaries = generate_community_summaries(graph, communities)
    
    # Process queries
    print("\nKnowledge graph ready. You can now ask questions.")
    print("Type 'exit' to quit.")
    
    while True:
        query = input("\nEnter your query: ")
        if query.lower() == 'exit':
            break
            
        result = process_query(query, graph, community_summaries)
        
        print("\n=== Retrieved Information ===")
        print(result["retrieved_info"])
        
        print("\n=== Response ===")
        print(result["response"])

if __name__ == "__main__":
    main()

Tips, Pitfalls, and Best Practices

Tips for Successful Implementation

  1. Start with clean, well-structured documents: The quality of your knowledge graph depends heavily on the quality of your input documents. Ensure they are well-organized, use consistent terminology, and provide comprehensive information.

  2. Balance chunk size carefully: When splitting documents for processing, strike a balance between chunks that are too large (computationally expensive) and too small (loss of context). A good starting point is 2000-3000 tokens with 10-20% overlap.

  3. Employ incremental indexing: Rather than rebuilding your knowledge graph from scratch when adding new documents, implement incremental indexing to update only the affected parts of the graph.

  4. Use community detection parameters wisely: Adjust community detection parameters based on your specific knowledge domain. Smaller resolution values create larger communities, while larger values create more fine-grained communities.

  5. Implement caching for frequent queries: Cache responses for common queries to improve response time and reduce computational load.

Common Pitfalls

  1. Poor entity extraction: LLaMA 3 may sometimes extract irrelevant entities or miss important ones. Consider using domain-specific entity lists to guide the extraction process.

  2. Overly complex knowledge graphs: Extremely large and complex knowledge graphs can become unwieldy and slow down retrieval. Consider pruning less important entities or using hierarchical graph structures.

  3. Inconsistent entity naming: The same entity might be referred to by different names across documents. Implement entity resolution to merge these variants.

  4. Overlooking evaluation: Without systematic evaluation, it's difficult to know if your GraphRAG system is actually outperforming a traditional RAG approach. Implement evaluation metrics to compare different approaches.

  5. Underestimating computational requirements: Building and querying knowledge graphs requires significant computational resources. Profile your implementation and optimize resource-intensive operations.

Best Practices

  1. Implement hybrid retrieval strategies: Combine graph-based retrieval with traditional vector search for the best results. Some queries benefit more from one approach than the other.

  2. Use domain-specific entity types: Customize entity types to match your specific domain. For technical documentation, this might include types like "API", "Function", "Parameter", etc.

  3. Apply iterative refinement: Use LLaMA 3's reasoning capabilities to refine both queries and retrieved information before generating the final response.

  4. Leverage the feedback loop: Collect user feedback on responses and use it to improve your knowledge graph and retrieval strategies.

  5. Consider temporal aspects: For domains with changing information, incorporate versioning in your knowledge graph to track changes over time.

  6. Optimize community summarization: The quality of community summaries significantly impacts global search effectiveness. Experiment with different summarization approaches to find what works best for your domain.

Conclusion & Takeaways

Advanced RAG techniques powered by LLaMA 3 represent a significant evolution in knowledge access systems. By moving beyond simple document chunking and vector similarity search toward structured knowledge representation, these systems can deliver more accurate, contextually relevant, and comprehensive responses.

Key takeaways from this exploration include:

  1. GraphRAG addresses fundamental limitations of traditional RAG approaches by preserving semantic relationships between concepts and enabling sophisticated retrieval strategies.

  2. LLaMA 3's enhanced capabilities provide the foundation for more intelligent information extraction, reasoning, and response generation.

  3. The combination of local and global search enables systems to handle both specific, focused queries and broad, conceptual questions.

  4. Continuous evaluation and improvement through feedback loops is essential for maintaining and enhancing system performance over time.

  5. Implementation complexity is balanced by quality improvements, making advanced RAG techniques worth considering for applications where response accuracy and depth are critical.

As language models and knowledge representation techniques continue to evolve, we can expect even more sophisticated approaches to emerge. Future directions might include multimodal knowledge graphs that incorporate images and audio, more dynamic knowledge updating mechanisms, and deeper integration with domain-specific reasoning capabilities.

For organizations dealing with large volumes of complex information, investing in advanced RAG techniques powered by models like LLaMA 3 can significantly enhance the value derived from their knowledge repositories. By implementing the approaches outlined in this article, you can build more intelligent information retrieval systems that truly understand the content they manage and the questions they're asked to answer.

Note: The code examples provided in this article are simplified for clarity and educational purposes. Production implementations would require additional error handling, optimization, and integration with specific technology stacks.