NLP(20)--知识图谱

前言

仅记录学习过程,有问题欢迎讨论

基于LLM的垂直领域问答方案:

  • 特点:不是通用语料;准确度要求高,召回率可以低(转人工);拓展性和可控性(改变特定内容的回答);确切的评价指标

实现:
传统方法:

  • 知识库+文本匹配 (问题转向量找知识库的相似度最高的问题来回答)

基于LLM:

1.直接生成:

  • 直接使用LLM获答案,然后使用SFT微调
  • 缺点:fine-tune的成本高;模型的泛用性下降;不易调整数据

2.RAG思路(推荐):

  • 段落召回+阅读理解(基于获取的信息给模型提示,期望获取一个更好的答案)
  • 召回的就是你垂直领域的内容,去给llm提示
  • 缺点:对LLM要求高,受召回算法限制(如果正确答案被丢弃,LLM无法挽回);生成结果不可控

3.基于知识体系(图谱)

  • 树形结构设置知识体系结构,然后给LLM去匹配最可能的知识点选择项,一级一级往下走
  • 缺点:需要大量标注数据,标注数据需要人工标注,标注成本高

知识图谱:

  • 知识图谱是图数据库的一种,用于存储和表示知识。
  • 如:姚明-身高-226cm(三元组)
  • 知识图谱的构建取决于你想要完成的任务,如果想要获取实体之间的关系,就要构建实体关系的图谱
以下为知识图谱的具体内容:

实体抽取:ner任务获取实体属性
关系抽取:

  • 限定领域:
    • 文本+实体送入模型 预测关系(本质还是分类任务)
    • 可以同时训练实体抽取和关系抽取,loss为二者相加
  • 开放领域:
    基于序列标注 (NER)

属性抽取:同关系抽取

知识融合:

  • 实体对齐:通过判断不同来源的属性的相似度
  • 实体消歧:根据上下文和语义关系进行实体消歧
  • 属性对齐:属性和属性值的相似度计算

知识推理:通过模型来推断两个实体的关系
知识表示:实体关系属性都转化为向量,都可以用id表示某个信息

图数据库的使用:

noe4j
使用NL2SQL把输入的文字变为sql查询

  • 方法1:基于模版+文本匹配,输入的文本去匹配对应的问题模版–再去匹配SQL(依赖模版,易于拓展,可以写复杂sql)
  • 方法2:semantic parsing(语义解析)–通过训练多个模型来获取sql(不易于拓展)
  • 方法3:用LLM写sql

代码展示

构建基于neo4j的知识图谱问答:
这里采用的是方法1,依赖问题模版。

import re
import json
import pandas
import itertools
from py2neo import Graph"""
使用neo4j 构建基于知识图谱的问答
需要自定义问题模板
"""class GraphQA:def __init__(self):# 启动neo4j neo4j consoleself.graph = Graph("http://localhost:7474", auth=("neo4j", "password"))schema_path = "kg_schema.json"templet_path = "question_templet.xlsx"self.load(schema_path, templet_path)print("知识图谱问答系统加载完毕!\n===============")# 对外提供问答接口def query(self, sentence):print("============")print(sentence)# 对输入的句子找和模板中最匹配的问题info = self.parse_sentence(sentence)  # 信息抽取print("info:", info)# 匹配模板templet_cypher_score = self.cypher_match(sentence, info)  # cypher匹配for templet, cypher, score, answer in templet_cypher_score:graph_search_result = self.graph.run(cypher).data()# 最高分命中的模板不一定在图上能找到答案, 当不能找到答案时,运行下一个搜索语句, 找到答案时停止查找后面的模板if graph_search_result:answer = self.parse_result(graph_search_result, answer)return answerreturn None# 加载模板def load(self, schema_path, templet_path):self.load_kg_schema(schema_path)self.load_question_templet(templet_path)return# 加载模板信息def load_question_templet(self, templet_path):dataframe = pandas.read_excel(templet_path)self.question_templet = []for index in range(len(dataframe)):question = dataframe["question"][index]cypher = dataframe["cypher"][index]cypher_check = dataframe["check"][index]answer = dataframe["answer"][index]self.question_templet.append([question, cypher, json.loads(cypher_check), answer])return# 返回输入中的实体,关系,属性def parse_sentence(self, sentence):# 先提取实体,关系,属性entitys = self.get_mention_entitys(sentence)relations = self.get_mention_relations(sentence)labels = self.get_mention_labels(sentence)attributes = self.get_mention_attributes(sentence)# 然后根据模板进行匹配return {"%ENT%": entitys,"%REL%": relations,"%LAB%": labels,"%ATT%": attributes}# 获取问题中谈到的实体,可以使用基于词表的方式,也可以使用NER模型def get_mention_entitys(self, sentence):return re.findall("|".join(self.entity_set), sentence)# 获取问题中谈到的关系,也可以使用各种文本分类模型def get_mention_relations(self, sentence):return re.findall("|".join(self.relation_set), sentence)# 获取问题中谈到的属性def get_mention_attributes(self, sentence):return re.findall("|".join(self.attribute_set), sentence)# 获取问题中谈到的标签def get_mention_labels(self, sentence):return re.findall("|".join(self.label_set), sentence)# 加载图谱信息def load_kg_schema(self, path):with open(path, encoding="utf8") as f:schema = json.load(f)self.relation_set = set(schema["relations"])self.entity_set = set(schema["entitys"])self.label_set = set(schema["labels"])self.attribute_set = set(schema["attributes"])return# 匹配模板的问题def cypher_match(self, sentence, info):# 根据提取到的实体,关系等信息,将模板展开成待匹配的问题文本templet_cypher_pair = self.expand_question_and_cypher(info)result = []for templet, cypher, answer in templet_cypher_pair:# 求相似度 距离函数score = self.sentence_similarity_function(sentence, templet)# print(sentence, templet, score)result.append([templet, cypher, score, answer])# 取最相似的result = sorted(result, reverse=True, key=lambda x: x[2])return result# 根据提取到的实体,关系等信息,将模板展开成待匹配的问题文本def expand_question_and_cypher(self, info):templet_cypher_pair = []# 模板的数据for templet, cypher, cypher_check, answer in self.question_templet:# 匹配模板cypher_check_result = self.match_cypher_check(cypher_check, info)if cypher_check_result:templet_cypher_pair += self.expand_templet(templet, cypher, cypher_check, info, answer)return templet_cypher_pair# 校验 减少比较次数def match_cypher_check(self, cypher_check, info):for key, required_count in cypher_check.items():if len(info.get(key, [])) < required_count:return Falsereturn True# 对于单条模板,根据抽取到的实体属性信息扩展,形成一个列表# info:{"%ENT%":["周杰伦", "方文山"], “%REL%”:[“作曲”]}def expand_templet(self, templet, cypher, cypher_check, info, answer):# 获取所有组合combinations = self.get_combinations(cypher_check, info)templet_cpyher_pair = []for combination in combinations:# 替换模板中的实体,属性,关系replaced_templet = self.replace_token_in_string(templet, combination)replaced_cypher = self.replace_token_in_string(cypher, combination)replaced_answer = self.replace_token_in_string(answer, combination)templet_cpyher_pair.append([replaced_templet, replaced_cypher, replaced_answer])return templet_cpyher_pair# 对于找到了超过模板中需求的实体数量的情况,需要进行排列组合# info:{"%ENT%":["周杰伦", "方文山"], “%REL%”:[“作曲”]}def get_combinations(self, cypher_check, info):slot_values = []for key, required_count in cypher_check.items():# 生成所有组合slot_values.append(itertools.combinations(info[key], required_count))value_combinations = itertools.product(*slot_values)combinations = []for value_combination in value_combinations:combinations.append(self.decode_value_combination(value_combination, cypher_check))return combinations# 将提取到的值分配到键上def decode_value_combination(self, value_combination, cypher_check):res = {}for index, (key, required_count) in enumerate(cypher_check.items()):if required_count == 1:res[key] = value_combination[index][0]else:for i in range(required_count):key_num = key[:-1] + str(i) + "%"res[key_num] = value_combination[index][i]return res# 将带有token的模板替换成真实词# string:%ENT1%和%ENT2%是%REL%关系吗# combination: {"%ENT1%":"word1", "%ENT2%":"word2", "%REL%":"word"}def replace_token_in_string(self, string, combination):for key, value in combination.items():string = string.replace(key, value)return string# 求相似度 距离函数 Jaccard相似度def sentence_similarity_function(self, sentence1, sentence2):# print("计算  %s %s"%(string1, string2))jaccard_distance = len(set(sentence1) & set(sentence2)) / len(set(sentence1) | set(sentence2))return jaccard_distance# 解析结果def parse_result(self, graph_search_result, answer):graph_search_result = graph_search_result[0]# 关系查找返回的结果形式较为特殊,单独处理if "REL" in graph_search_result:graph_search_result["REL"] = list(graph_search_result["REL"].types())[0]answer = self.replace_token_in_string(answer, graph_search_result)return answerif __name__ == '__main__':graph = GraphQA()res = graph.query("谁导演的不能说的秘密")print(res)res = graph.query("发如雪的谱曲是谁")print(res)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/17679.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

std::mutex

结论&#xff1a; 最终std::mutex 会调用pthread_mutex_t 相关接口 1 std::mutex 定义封装关键数据&#xff1a;typedef __gthread_mutex_t #ifdef _GLIBCXX_HAS_GTHREADS// Common base class for std::mutex and std::timed_mutexclass __mutex_base{protected:typedef __g…

数据结构初阶 栈

一. 栈的基本介绍 1. 基本概念 栈是一种线性表 是一种特殊的数据结构 栈顶&#xff1a;进行数据插入和删除操作的一端 另一端叫做栈底 压栈&#xff1a;插入数据叫做压栈 压栈的数据在栈顶 出栈&#xff1a; 栈的删除操作叫做出栈 出栈操作也是在栈顶 栈遵循一个原则 叫做…

Python深度学习:【模型系列】一文搞懂Transformer架构的三种注意力机制

文章目录 1. 什么是注意力机制?2. Transformer 的注意力层2.1 注意力机制基础2.2 理解Q,K,V2.3 交叉注意力层2.4 全局自注意力层2.5 因果注意力层3. 位置编码4. 多头注意力机制5. 总结1. 什么是注意力机制? 注意力机制最初受到人类视觉注意力的启发,目的是让模型在处理大…

JavaEE:Servlet创建和使用及生命周期介绍

目录 ▐ Servlet概述 ▐ Servlet的创建和使用 ▐ Servlet中方法介绍 ▐ Servlet的生命周期 ▐ Servlet概述 • Servlet是Server Applet的简称&#xff0c;意思是 用Java编写的服务器端的程序&#xff0c;Servlet被部署在服务器中&#xff0c;而服务器负责管理并调用Servle…

2024.5.21 作业 xyt

今日课堂内容&#xff1a;域套接字 TCP流式套接字 //服务器 #include <myhead.h> int main(int argc, const char *argv[]) {//1、为通信创建一个端点int sfd socket(AF_UNIX, SOCK_STREAM, 0);//参数1&#xff1a;说明使用的是ipv4通信域//参数2&#xff1a;说明使用…

ffpmeg之avformat_network_init和avdevice_register_all函数

avformat_network_init 如果利用ffpmeg库拉取视频流或者通过http协议打开视频文件播放&#xff0c;涉及到网络IO操作的&#xff0c;在应用程序之前首先需要调用avformat_network_init函数&#xff0c;该函数调用后就实现了对ffmpeg模块IO的一些初始化&#xff0c;后续就可以利…

HTML静态网页成品作业(HTML+CSS)——动漫海绵宝宝介绍网页(5个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有5个页面。 二、作品演示 三、代…

【前端笔记】记录一个能优化Echarts Geo JSON大小的网站

前端在使用Echarts等可视化图表库会不可避免遇到的问题&#xff0c;渲染地图的数据太大。 而有那么一个网站能给予这个问题一个解决方案&#xff1a;链接在此 使用方法很简单&#xff0c;首先先进入网站&#xff0c;如果进入了会是这个页面&#xff1a; 接着&#xff0c;选择一…

代码随想录算法训练营第四十三天|

518.零钱兑换II 典型的完全背包问题&#xff0c;但这里是求有多少种组合方式&#xff0c;所以递推公式变为 dp[j] dp[j - coins[i]]; 377. 组合总和 Ⅳ 也是完全背包问题&#xff0c;但是需要求排列而不是组合&#xff0c;所以需要先遍历背包容量&#xff0c;再遍历物品。 …

HCIP的学习(25)

VLAN间通讯技术 使用多臂路由的方式 ​ 路由器的物理接口默认是不识别802.1Q标签的&#xff0c;所以&#xff0c;交换机连接路由器的接口在发送数据帧时&#xff0c;应该将标签剥离。----一般常使用Access接口配置。 单臂路由 ​ 所谓的单臂路由&#xff0c;实际上试讲路由器…

【主流分布式算法总结】

文章目录 分布式常见的问题常见的分布式算法Raft算法概念Raft的实现 ZAB算法Paxos算法 分布式常见的问题 分布式场景下困扰我们的3个核心问题&#xff08;CAP&#xff09;&#xff1a;一致性、可用性、分区容错性。 1、一致性&#xff08;Consistency&#xff09;&#xff1a;…

Docker是什么?使用场景作用及Docker的安装和启动详解

目录 Docker是什么&#xff1f; Docker的发展 Docker的安装 Docker使用 Docker的运行机制 第一个Docker容器 进入Docker容器 客户机访问容器 Docker是什么&#xff1f; Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从 Apache2.0 协议开源。 Docker …

记录深度学习GPU配置,下载CUDA与cuDnn

目标下载: cuda 11.0.1_451.22 win10.exe cudnn-11.0-windows-x64-v8.0.2.39.zip cuda历史版本网址 CUDA Toolkit Archive | NVIDIA Developer 自己下载过11.0.1版本 点击下载local版本,本地安装,有2个多GB,很大,我不喜欢network版本,容易掉线 cuDnn https://developer.nvi…

设置AXI主寄存器切片和AXI数据FIFO

设置AXI主寄存器切片和AXI数据FIFO 打开MHS文件&#xff0c;并为每个AXI主机设置启用寄存器切片/启用数据FIFO。到 确定正确的设置&#xff0c;使用下表中的信息搜索MHS。 进行搜索时&#xff0c;将<intf_name>替换为相关的BUS_INTERFACE名称。 例如&#xff0c;BUS_INTE…

Docker部署SpringBoot项目(jar包+Mysql)

部署Java项目 项目准备准备Java项目镜像准备配置网络 部署项目细节展示 项目准备 准备Java项目 hmall项目是一个maven聚合项目&#xff0c;使用IDEA打开hmall项目&#xff0c;查看项目结构如图&#xff1a; 我们要部署的就是其中的hm-service&#xff0c;其中的配置文件采用…

《一地霜白》读书笔记

1.3.6 街灯明灭&#xff0c;勾缀成行&#xff0c;为了生者与死者 “很多年过去了。回头看&#xff0c;沿着一排暗中的街灯&#xff0c;两三盏灭了&#xff0c;郁闷中有意外的欣喜&#xff1a;街灯明灭&#xff0c;勾缀成行&#xff0c;为了生者与死者。” 童年、青少年在人的…

还在使用Swagger吗?ApifoxHelper插件隆重登场

目录 前言 安装Apifox Idea插件安装 插件令牌配置 获取令牌 Idea配置令牌 快速上手 同步文档 查看文档 结语&#xff1a; 前言 最近发现一款特别好用的插件&#xff0c;帮助开发者快速生成接口文档。ApifoxHelper插件实现代码零侵入&#xff0c;只需要写上相应注释即可…

K8s种的service配置

什么是service 官方的解释是:   k8s中最小的管理单元是pod&#xff1b;而service是 将运行在一个或一组 Pod 上的网络应用程序公开为网络服务的方法;   Kubernetes 中 Service 的一个关键目标是让你无需修改现有应用以使用某种服务发现机制。 你可以在 Pod 集合中运行代码…

一个程序员的牢狱生涯(42)事件

星期一 事件 老郅安排我一个人在内班办公室等着,并没让我去女号子,我一个人来回踱着步,着急的等待着。 在老郅进入女号子后,我悄悄地踱着步走到里间办公室听。只听见老郅在询问着丽姐是怎么回事,丽姐有点着急地说道: “我发现杨x躺着,而且精神不好,就‘打博’(北方方言…