Expand:将一个实体扩张至该节点所有相关的实体集

    def expand(self, entity_name):
        query = (
            "MATCH (a:Entity {name: $entity_name})-[r]->(b:Entity) "
            "RETURN b AS child,r.type AS relation_type"
        )
        with self.driver.session() as session:
            result = session.run(query, entity_name=entity_name)
            linked_nodes = []

            for record in result:
                if record["child"].id is not None and record["child"].id != '':
                    linked_nodes.append(
                        {
                            "id": record["child"].id,
                            "name": record["child"]["name"],
                            "type": record["relation_type"],
                        }
                    )
            return linked_nodes

Describe:返回该实体的所有描述(Description)

    def describe(self, entity_name):
        query = (
            "MATCH (a:Entity {name: $entity_name})-[r]->(b:Description) "
            "RETURN b AS des,r.type AS relation_type"
        )
        with self.driver.session() as session:
            result = session.run(query, entity_name=entity_name)

            types = []
            descriptions = []
            for record in result:
                now_type = record["relation_type"]
                if now_type not in types:
                    matched = []
                    types.append(now_type)
                    for flag in result:
                        if flag["relation_type"] == now_type:
                            matched.append(
                                {"name": flag["des"]["name"],
                                 "page": flag["des"]["page_num"]
                                 })
                    descriptions.append(
                        {
                            "type": now_type,
                            "data": matched
                        }
                    )
        return descriptions

Struct:生长基于指定实体在知识图谱中的x层y节点关键子图

    def struct(self, entity_name):
        query = (
            """
            MATCH (e:Entity {name: $entity_name})-[r1:RELATION]->(first_level)
            WITH e, r1, first_level
            MATCH (first_level)-[r2:RELATION]->(second_level)
            WITH e, r1, first_level, r2, second_level
            ORDER BY first_level, second_level
            WITH e, r1, first_level, collect(second_level)[..2] AS limited_second_level_nodes, collect(r2)[..2] AS limited_second_level_rels
            UNWIND range(0, size(limited_second_level_nodes)-1) AS idx
            WITH e, r1, first_level, limited_second_level_nodes[idx] AS second_level, limited_second_level_rels[idx] AS r2
            WITH e, r1, first_level, r2, second_level
            LIMIT 20
            RETURN e, r1, first_level, r2, second_level, 
                   'e1: ' + id(e) + ', e2: ' + id(first_level) + ', e3: ' + id(second_level) + 
                   ', r1: ' + type(r2) + ' (source: ' + id(startNode(r2)) + ', target: ' + id(endNode(r2)) + ')' AS path
            """
        )
        with self.driver.session() as session:
            result = session.run(query, entity_name=entity_name)
            data = []
            links = []
            vertex_ids = set()
            edge_ids = set()

            for record in result:
                node = record["e"]
                first_level = record["first_level"]
                second_level = record["second_level"]
                r1 = record["r1"]
                r2 = record["r2"]

                if node.id not in vertex_ids:
                    data.append({
                        "id": node.id,
                        "name": node["name"],
                        "des": node["name"],
                        "symbolSize": 50,
                        "category": 0,
                    })
                    vertex_ids.add(node.id)

                if first_level.id not in vertex_ids:
                    data.append({
                        "id": first_level.id,
                        "name": first_level["name"],
                        "des": first_level["name"],
                        "symbolSize": 50,
                        "category": 1,
                    })
                    vertex_ids.add(first_level.id)

                if second_level.id not in vertex_ids:
                    data.append({
                        "id": second_level.id,
                        "name": second_level["name"],
                        "des": second_level["name"],
                        "symbolSize": 50,
                        "category": 2,
                    })
                    vertex_ids.add(second_level.id)

                if r1.id not in edge_ids:
                    links.append({
                        "name": r1.type,
                        "des": r1["type"],
                        "source": r1.start_node.id,
                        "target": r1.end_node.id,
                    })
                    edge_ids.add(r1.id)

                if r2.id not in edge_ids:
                    links.append({
                        "name": r2.type,
                        "des": r2["type"],
                        "source": r2.start_node.id,
                        "target": r2.end_node.id,
                    })
                    edge_ids.add(r2.id)

            return data, links

    def exercise(self, entity_name, questions=None):
        if questions is None:
            questions = []
        query = (
            """
            MATCH (e:Entity {name: $entity_name})-[r1:Exercise]->(q)
            WHERE q.answer_text IS NOT NULL AND q.answer_text <> ''
            RETURN q AS question
            LIMIT 20
            """
        )
        with self.driver.session() as session:
            result = session.run(query, entity_name=entity_name)
            for record in result:
                text = record['question']['problem_text']
                answer = record['question']['answer_text']
                id = record['question'].id
                type = record['question']['problem_type']
                questions.append({
                    "text": text,
                    "answer": answer,
                    "type": type,
                    "id": id,
                })
            if len(questions) < 3:
                expands = self.expand(entity_name)
                for expand in expands:
                    self.exercise(expand["name"], questions)
            return questions

向量化计划通过Faiss向量数据库实现.

具体路线流程如下图:

import faiss
import numpy as np
from sentence_transformers import SentenceTransformer

def read_text_file(file_path):
    with open(file_path, 'r', encoding='utf-8') as file:
        lines = file.readlines()
    return [line.strip() for line in lines if line.strip()]

def text_to_vectors(texts, model_name='all-MiniLM-L6-v2'):
    model = SentenceTransformer(model_name)
    vectors = model.encode(texts, show_progress_bar=True)
    return vectors

def build_faiss_index(vectors, index_path='faiss_index'):
    d = vectors.shape[1]
    index = faiss.IndexFlatL2(d)
    index.add(vectors)
    faiss.write_index(index, index_path)

def search_faiss_index(query_vector, index_path='faiss_index', top_k=5):
    index = faiss.read_index(index_path)
    distances, indices = index.search(query_vector, top_k)
    return distances, indices

def main():
    txt_file_path = 'ComputerNetwork.txt'
    texts = read_text_file(txt_file_path)
    vectors = text_to_vectors(texts)
    build_faiss_index(vectors)
    query_text = "查询文本"
    query_vector = text_to_vectors([query_text])
    distances, indices = search_faiss_index(query_vector)
    
    print("查询结果:")
    for i, index in enumerate(indices[0]):
        print(f"文本: {texts[index]}, 距离: {distances[0][i]}")

if __name__ == "__main__":
    main()

文本嵌入后,考虑对嵌入的向量归入Faiss库 

归入Faiss向量库

创建L2距离的Faiss索引

dimension = embedding_out_dim  # 经过Embedding后的向量维度
index = faiss.IndexFlatL2(dimension)  # 使用L2距离的平面索引

使用Faiss索引查找5个最近邻向量 

query_vector = vector
k = 5  # 查找前5个最近邻
distances, indices = index.search(query_vector, k)
print("最近邻索引:", indices)
print("最近邻距离:", distances)

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐