How RAG-Anything Handles Weighted Relationship Scoring in Its Multimodal Knowledge Graph

RAG-Anything assigns a default weight of 10.0 to hierarchical "belongs_to" edges during graph construction, then multiplies these weights against vector similarity scores during retrieval to rank multimodal results.

Building multimodal RAG systems requires more than chunked text and vector search.weighted relationship scoring in knowledge graphs bridges the gap between unstructured data and structured reasoning. RAG-Anything, an open-source multimodal RAG framework built on LightRAG, implements this through explicit edge weights that influence retrieval ranking. This article examines how the system calculates, stores, and applies these weights using actual source code from the HKUDS/RAG-Anything repository.


How the Multimodal Knowledge Graph Stores Relationship Weights

RAG-Anything extends LightRAG's graph backend to handle multimodal entities—text snippets, image regions, table cells, and other extracted elements. Every relationship between these entities carries a weight field in its edge metadata.

Edge Structure with Weight Field

When the pipeline creates a relationship, it constructs a dictionary with these fields:

{
    "src_id": "<child_entity>",
    "tgt_id": "<parent_modal_entity>",
    "description": "Entity belongs to parent modal",
    "keywords": "belongs_to,part_of,contained_in",
    "source_id": "<chunk_id>",
    "weight": 10.0,
    "file_path": "<origin>"
}

The weight field is a floating-point value persisted through LightRAG's upsert_edge() method. This weight remains accessible during retrieval queries where the scoring layer combines it with semantic similarity scores.


How "Belongs_To" Edges Receive Their Default Weight

The most common relationship type in RAG-Anything's multimodal graph is "belongs_to"—a hierarchical edge connecting child entities to their parent modal container. The system assigns these edges a fixed weight of 10.0 during construction.

Weight Assignment in processor.py

The core implementation resides in raganything/processor.py at line 1315. Here the pipeline iterates through extracted entities and creates parent-child relationships:

belongs_to_relation = {
    "src_id": entity_name,
    "tgt_id": modal_entity_name,
    "description": f"Entity {entity_name} belongs to {modal_entity_name}",
    "keywords": "belongs_to,part_of,contained_in",
    "source_id": chunk_id,
    "weight": 10.0,                     # ← fixed default weight

    "file_path": file_path,
}
await self.knowledge_graph_inst.upsert_edge(
    entity_name, modal_entity_name, belongs_to_relation
)

Source: raganything/processor.py, line 1315

This hardcoded weight ensures that hierarchical relationships dominate the scoring function. The value 10.0 was chosen to significantly amplify these edges compared to potential noise from weaker associations.


Alternative Path: Weighted Edges in modalprocessors.py

RAG-Anything supports multiple processing pipelines. The modalprocessors.py module provides an alternate entry point for manually constructed multimodal chunks, using the same weight assignment pattern.

Consistent Weight Pattern at Line 770


# From modalprocessors.py edge creation logic

edge_data = {
    "src_id": child_id,
    "tgt_id": parent_id,
    "relationship_type": "belongs_to",
    "weight": 10.0,  # Same default as processor.py

    # ... additional metadata

}
await kg.upsert_edge(child_id, parent_id, edge_data)

Source: raganything/modalprocessors.py, line 770

This parallel implementation ensures weight consistency regardless of which pipeline processes the multimodal content. Both paths funnel into the same LightRAG graph backend where weights are stored and retrieved.


How Weighted Scores Influence Retrieval Ranking

The retrieval pipeline in RAG-Anything combines vector similarity with graph-based relevance, using edge weights as multiplicative factors in the scoring function.

Scoring Mechanism

During query execution, the system:

  1. Retrieves candidate nodes via vector similarity search against chunk embeddings
  2. Traverses outgoing edges from each candidate to gather relationship context
  3. Multiplies base similarity scores by edge weights to produce final rankings

# Conceptual scoring flow (pseudo-code based on LightRAG integration)

for candidate in vector_candidates:
    base_score = candidate["embedding_similarity"]
    
    # Accumulate weighted edge contributions

    graph_bonus = 0
    for edge in await graph.get_out_edges(candidate["id"]):
        edge_relevance = calculate_edge_relevance(edge, query)
        graph_bonus += edge["weight"] * edge_relevance  # weight applied here

    
    candidate["final_score"] = base_score + graph_bonus

The default weight of 10.0 for "belongs_to" edges means these hierarchical relationships contribute ten times more to the score than a hypothetical unweighted edge would. This prioritizes results that maintain semantic coherence with their parent modal context.


Customizing Weights for Domain-Specific Relationships

RAG-Anything's weight system is extensible. Developers can override the default 10.0 value when constructing custom relationship types.

Example: Lower Weight for Weak Associations


# Custom relationship with reduced weight for loose connections

references_relation = {
    "src_id": "eq_42",
    "tgt_id": "section_3",
    "description": "Equation 42 references Section 3",
    "keywords": "references,cites",
    "source_id": chunk_id,
    "weight": 4.5,  # Lower than belongs_to default

    "file_path": file_path,
}
await self.knowledge_graph_inst.upsert_edge(
    "eq_42", "section_3", references_relation
)

This flexibility allows fine-tuning of retrieval behavior. Critical hierarchical links can retain high weights while peripheral associations receive lower priority.


Key Source Files for Weighted Relationship Scoring

File Purpose Key Location
raganything/processor.py Core pipeline for multimodal entity extraction and "belongs_to" edge creation with default weight Line 1315: belongs_to_relation definition
raganything/modalprocessors.py Alternative processing path for manual multimodal chunks, same weight pattern Line 770: Edge creation logic
README.md High-level documentation of weighted scoring strategy "Weighted Relationship Scoring" section
raganything/prompt.py LLM prompts generating relationship metadata (keywords, descriptions) used in edge construction
raganything/callbacks.py Pub-sub hooks enabling dynamic weight modification during processing

Summary

  • RAG-Anything's multimodal knowledge graph stores relationship weights as floating-point values in edge metadata through LightRAG's upsert_edge() API.

  • Default weight of 10.0 is hardcoded for "belongs_to" hierarchical edges in processor.py (line 1315) and modalprocessors.py (line 770), ensuring parent-child relationships dominate retrieval scoring.

  • Retrieval scoring combines vector similarity with graph traversal, multiplying base scores by edge weights to produce final rankings.

  • Extensible design allows developers to override default weights for custom relationship types, enabling domain-specific tuning of retrieval behavior.


Frequently Asked Questions

What is the default weight value for relationships in RAG-Anything?

The default weight is 10.0, assigned to all "belongs_to" edges created during multimodal processing. This value is hardcoded in both processor.py and modalprocessors.py to ensure consistent hierarchical relationship strength across the knowledge graph.

How does the weight value affect search results in RAG-Anything?

The weight acts as a multiplicative factor during retrieval scoring. When the system ranks candidate results, it multiplies base vector similarity scores by the edge weights from traversed relationships. The default 10.0 value for "belongs_to" edges means hierarchical connections contribute substantially more to final rankings than they would with unweighted edges.

Can developers customize relationship weights in RAG-Anything?

Yes. While the "belongs_to" relationship uses a fixed 10.0 default, developers can specify custom weights when constructing other relationship types. Simply pass a different weight value in the edge dictionary before calling knowledge_graph_inst.upsert_edge(). This enables fine-tuning for domain-specific scenarios where certain relationships should have stronger or weaker influence on retrieval.

Where in the RAG-Anything codebase are relationship weights assigned?

Relationship weights are assigned in two primary locations:

  • raganything/processor.py at line 1315: The main multimodal pipeline creates "belongs_to" edges with weight: 10.0 when processing extracted entities.
  • raganything/modalprocessors.py at line 770: An alternative processing path for manual multimodal chunks uses the same weight assignment pattern.

Both locations feed into LightRAG's graph storage via upsert_edge() calls.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →