Skip to content

Latest commit

 

History

History
177 lines (133 loc) · 5.19 KB

File metadata and controls

177 lines (133 loc) · 5.19 KB

Filter和指针机制分析

✅ 是的,这里使用了Filter和类似指针的机制

1. Filter(过滤器)的使用

filter_contexts_by_dual_threshold 函数

def filter_contexts_by_dual_threshold(
    results: list,
    query_embedding: list[float],
    threshold_chunk: float = 0.7,
    threshold_summary: float = 0.7,
):
    filtered = []  # 创建新的过滤列表
    for r in results:
        # 计算相似度
        sim_chunk = cosine_similarity(query_embedding, r["embedding"])
        sim_summary = cosine_similarity(query_embedding, r["summary_embedding"])
        
        # 过滤条件:两个相似度都要 >= 0.7
        if sim_chunk >= threshold_chunk and sim_summary >= threshold_summary:
            filtered.append(r)  # 只保留满足条件的项
    
    return filtered

特点

  • ✅ 使用循环+条件判断实现过滤
  • ✅ 不是Python内置的filter()函数,而是手动实现
  • ✅ 返回新的过滤后的列表

2. 类似指针/引用的机制

Python中没有显式指针,但使用了以下几种类似机制:

A. 使用字典和ID作为"指针"(引用对象)

# build_index.py 中使用模块级字典存储table_name
build_index_on_chunks._db_table_map = {}
build_index_on_chunks._db_table_map[id(db)] = table_name

# rag_complete.py 中通过id(db)查找table_name
db_id = id(db)
table_name = build_index.build_index_on_chunks._db_table_map.get(db_id)

原理

  • id(db) 返回对象的唯一标识符(类似于内存地址)
  • 使用字典存储 对象ID -> table_name 的映射
  • 通过对象ID快速查找关联的数据

B. 使用字典映射关联Chunk和Abstract

def enrich_results_with_summary_embeddings(results, ...):
    # 创建映射表:pair_id -> tree_node embedding
    tree_node_map = {}  # 类似指针表
    
    # 第一遍:收集tree_node的embedding
    for r in results:
        if r.get("type") == "tree_node":
            pair_id = r.get("pair_id")
            tree_node_map[pair_id] = r["embedding"]  # 存储引用
    
    # 第二遍:通过pair_id查找对应的tree_node
    for r in results:
        if r.get("type") == "raw_chunk":
            chunk_id = r.get("chunk_id")
            pair_id = chunk_id // 2  # 计算对应的pair_id
            
            # 通过pair_id查找tree_node的embedding(类似解引用)
            if pair_id in tree_node_map:
                r["summary_embedding"] = tree_node_map[pair_id]

原理

  • tree_node_map 类似于指针表,存储 pair_id -> embedding 的映射
  • 通过 chunk_id // 2 计算对应的 pair_id
  • 通过 pair_id 在映射表中查找对应的abstract embedding

C. 直接修改对象引用(Python对象引用)

# 在enrich_results_with_summary_embeddings中
for r in results:
    if r.get("type") == "raw_chunk":
        # 直接修改原对象r,添加summary_embedding字段
        r["summary_embedding"] = tree_node_map[pair_id]

原理

  • Python中,r 是对字典对象的引用
  • 直接修改 r["summary_embedding"] 会修改原对象
  • 多个引用指向同一个对象时,修改会反映到所有引用上

3. 数据结构对比

传统指针(C/C++)

// C语言中的指针
int* ptr = &value;  // ptr指向value的地址
int val = *ptr;     // 解引用获取值

Python中的等价实现

# 使用字典作为指针表
pointer_map = {}
pointer_map[id(obj)] = value  # 存储对象ID到值的映射
value = pointer_map[id(obj)]  # 通过对象ID查找值

# 或者直接使用对象引用(Python默认行为)
obj = {}  # obj是对字典对象的引用
obj["key"] = value  # 直接修改对象

4. 关键代码位置

Filter实现

# rag_base/rag_complete.py, line 153-187
def filter_contexts_by_dual_threshold(...):
    filtered = []
    for r in results:
        # 过滤逻辑
        if condition:
            filtered.append(r)
    return filtered

"指针"机制实现

# rag_base/build_index.py, line 134-136
build_index_on_chunks._db_table_map = {}
build_index_on_chunks._db_table_map[id(db)] = table_name

# rag_base/rag_complete.py, line 203-222
db_id = id(db)  # 获取对象ID
table_name = build_index.build_index_on_chunks._db_table_map.get(db_id)

# rag_base/rag_complete.py, line 89-104
tree_node_map = {}  # 指针表
tree_node_map[pair_id] = r["embedding"]  # 存储
r["summary_embedding"] = tree_node_map[pair_id]  # 解引用

📊 总结

Filter(过滤器)

  • 使用了:通过循环+条件判断实现过滤
  • 类型:手动实现的过滤逻辑,不是Python内置的filter()
  • 位置filter_contexts_by_dual_threshold() 函数

指针/引用机制

  • 使用了:通过多种方式实现类似指针的功能
    1. 使用id()和字典存储对象关联(类似指针表)
    2. 使用字典映射关联chunk和abstract(通过pair_id)
    3. Python对象引用机制(直接修改对象)

设计优势

  1. Filter:明确的过滤逻辑,易于理解和调试
  2. "指针"机制
    • 通过ID映射避免重复存储
    • 通过字典查找实现快速关联
    • 利用Python对象引用实现原地修改