From 2751297bb5f9dc43edfdc82df4b603be2fd5256e Mon Sep 17 00:00:00 2001 From: Eureka Date: Thu, 3 Apr 2025 15:14:43 +0800 Subject: [PATCH] GraphAGE --- .../zh/docs/DataVec/DataVec-tutorials.md | 1 + .../DataVec/figures/openGauss-AGEGraph.png | Bin 0 -> 32737 bytes .../zh/docs/DataVec/openGauss-AGEGraph.md | 214 ++++++++++++++++++ content/docs-lite/zh/menu/index.md | 1 + content/zh/docs/DataVec/DataVec-tutorials.md | 1 + .../DataVec/figures/openGauss-AGEGraph.png | Bin 0 -> 32737 bytes content/zh/docs/DataVec/openGauss-AGEGraph.md | 214 ++++++++++++++++++ content/zh/menu/index.md | 1 + 8 files changed, 432 insertions(+) create mode 100644 content/docs-lite/zh/docs/DataVec/figures/openGauss-AGEGraph.png create mode 100644 content/docs-lite/zh/docs/DataVec/openGauss-AGEGraph.md create mode 100644 content/zh/docs/DataVec/figures/openGauss-AGEGraph.png create mode 100644 content/zh/docs/DataVec/openGauss-AGEGraph.md diff --git a/content/docs-lite/zh/docs/DataVec/DataVec-tutorials.md b/content/docs-lite/zh/docs/DataVec/DataVec-tutorials.md index fdf3cc46f..8932c25af 100644 --- a/content/docs-lite/zh/docs/DataVec/DataVec-tutorials.md +++ b/content/docs-lite/zh/docs/DataVec/DataVec-tutorials.md @@ -5,3 +5,4 @@ - [打破AI黑盒,拥抱开源力量:基于openGauss+DeepSeek的本地知识库,打造你的专属AI助手!](openGauss-RAG实践.md) - [openGauss DataVec + Dify, 快速搭建你的智能助手平台](openGauss-Dify.md) - [SpringBoot 集成 openGauss DataVec, 实现向量化检索](openGauss-Springboot.md) +- [openGauss AGEGraph + 大模型实现 GraphRAG,助力更强 RAG](openGauss-AGEGraph.md) diff --git a/content/docs-lite/zh/docs/DataVec/figures/openGauss-AGEGraph.png b/content/docs-lite/zh/docs/DataVec/figures/openGauss-AGEGraph.png new file mode 100644 index 0000000000000000000000000000000000000000..b2a00fb186c0c91df15ada70d4469017d10f423f GIT binary patch literal 32737 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/tcp opengauss-age + +``` +#### 1.2 AGE插件安装 + +``` +#进入openGauss容器中 253714c9c869为 CONTAINER ID +docker exec -it 253714c9c869 bash + +#切换到omm用户 +su omm + +#omm用户,连接数据库,默认使用omm数据库 +gsql -r + +#连接数据库后,omm数据库安装age插件 +create extension age; + +#退出数据库连接 +\q + +``` + +#### 1.3 python依赖安装 + +``` +pip install -U langchain_community langchain langgraph langchain-ollama langchain-experimental langchain-openai +``` +下载已适配的 langchain_community 仓库,操作如下: + +##### 1.3.1 下载适配好的langchain_community仓 +``` +git clone https://gitee.com/lin-qiang123/langchain.git +``` +##### 1.3.2 查找pip 安装的langchain_community位置 +``` +pip show langchain_community +``` +输出 + +``` +Name: langchain-community +Version: 0.3.20 +Summary: Community contributed LangChain integrations. +Home-page: +Author: +Author-email: +License: MIT +Location: c:\users\test\appdata\local\programs\python\python310\lib\site-packages #依赖库安装的位置 +Requires: numpy, PyYAML, aiohttp, tenacity, dataclasses-json, langchain, httpx-sse, SQLAlchemy, pydantic-settings, langchain-core, langsmith, requests +Required-by: langchain-experimental +``` + +##### 1.3.3 替换langchain-community +在git clone 下来的代码仓中,找到langchain\libs\community\langchain_community文件夹,复制并且覆盖到`Location`显示的文件夹中 + + +### 2. 利用 模型和 openGauss AGEGraph 快速构建知识图谱和检索 +本文使用百炼大模型,取得api-key,并且配置DASHSCOPE_API_KEY环境变量 +#### 2.1 初始化大模型 + +``` +from langchain_community.llms import Tongyi +import os + +os.environ["DASHSCOPE_API_KEY"] = "sk-**" +graph_llm =Tongyi(model="qwen-plus", temperature=0, base_url="https://dashscope.aliyuncs.com/compatible-mode/v1") + +``` +#### 2.2 通过大模型提取文本数据中的实体和关系 + + +``` +from langchain_core.documents import Document +from langchain_experimental.graph_transformers import LLMGraphTransformer + +#设置需要提取的实体类型和关系 +llm_transformer = LLMGraphTransformer( + llm=graph_llm, + allowed_nodes=["Person", "Organization", "Location", "Award", "ResearchField"], + allowed_relationships = ["SPOUSE", "AWARD", "FIELD_OF_RESEARCH", "WORKS_AT", "IN_LOCATION"], +) + +text = """ +Marie Curie, 7 November 1867 – 4 July 1934, was a Polish and naturalised-French physicist and chemist who conducted pioneering research on radioactivity. +She was the first woman to win a Nobel Prize, the first person to win a Nobel Prize twice, and the only person to win a Nobel Prize in two scientific fields. +Her husband, Pierre Curie, was a co-winner of her first Nobel Prize, making them the first-ever married couple to win the Nobel Prize and launching the Curie family legacy of five Nobel Prizes. +She was, in 1906, the first woman to become a professor at the University of Paris. +Also, Robin Williams. +""" + +# 将文本转化为图 +documents = [Document(page_content=text)] +graph_documents = llm_transformer.convert_to_graph_documents(documents) + + +print(f"Nodes from graph doc:{graph_documents[0].nodes}") +print(f"Relationships from graph doc:{graph_documents[0].relationships}") +``` +输出 + +``` +Nodes from graph doc:[Node(id='Nobel Prize', type='Award', properties={}), Node(id='University of Paris', type='Organization', properties={}), Node(id='Marie Curie', type='Person', properties={}), Node(id='radioactivity', type='ResearchField', properties={}), Node(id='Pierre Curie', type='Person', properties={})] +Relationships from graph doc:[Relationship(source=Node(id='Marie Curie', type='Person', properties={}), target=Node(id='radioactivity', type='ResearchField', properties={}), type='FIELD_OF_RESEARCH', properties={}), Relationship(source=Node(id='Marie Curie', type='Person', properties={}), target=Node(id='Nobel Prize', type='Award', properties={}), type='AWARD', properties={}), Relationship(source=Node(id='Marie Curie', type='Person', properties={}), target=Node(id='Nobel Prize', type='Award', properties={}), type='AWARD', properties={}), Relationship(source=Node(id='Marie Curie', type='Person', properties={}), target=Node(id='Pierre Curie', type='Person', properties={}), type='SPOUSE', properties={}), Relationship(source=Node(id='Pierre Curie', type='Person', properties={}), target=Node(id='Nobel Prize', type='Award', properties={}), type='AWARD', properties={}), Relationship(source=Node(id='Marie Curie', type='Person', properties={}), target=Node(id='University of Paris', type='Organization', properties={}), type='WORKS_AT', properties={})] +``` +#### 2.3 实例化 openGauss AGEGraph 客户端,持久化图数据 + +``` +from langchain_community.graphs.age_graph import AGEGraph + +conf = { + "database": "omm", + "user": "gaussdb", + "password": "YourPassoword", + "host": "Your IP", + "port": 8888, + "sslmode": "disable" +} +graph=AGEGraph(graph_name='graph_test1',conf=conf,create=True) +graph.add_graph_documents(graph_documents) +graph.refresh_schema() + +``` + +#### 2.4 大模型 Text2Cypher:提取问题关键词并生成图检索语句 + +通过增加提示词`cypher_prompt`,可以让大模型生成的图查询语句更加精准 +``` +from langchain_core.prompts import PromptTemplate +from langchain.chains import GraphCypherQAChain + +cypher_prompt = PromptTemplate( + template="""你是 AGE Cypher 查询生成的专家。 + 使用以下架构生成一个 Cypher 查询,以回答给定问题。 + 不要出现name和properties和cypher + + 架构: + {schema} + + 问题:{question} + + Cypher 查询:""", + input_variables=["schema", "question"], +) + +chain = GraphCypherQAChain.from_llm( + graph_llm, graph=graph, verbose=True, allow_dangerous_requests=True, cypher_validation=True, return_intermediate_steps=True,cypher_prompt=cypher_prompt +) + +question = "Who get Nobel Prize ?" +result = chain.invoke({"query": question}) +``` +输出 + +> Entering new GraphCypherQAChain chain... +Generated Cypher: +MATCH (p:Person)-[:AWARD]->(a:Award) +WHERE a.id = "Nobel Prize" +RETURN p.id +Full Context: +[{'p_id': 'Pierre Curie'}, {'p_id': 'Marie Curie'}] + +### 3. 大模型依据检索的图数据生成回答 + +#### 3.1 设置提示词 +``` +prompt = PromptTemplate( + template="""You are an assistant for question-answering tasks. + Use the following pieces of retrieved context from a graph database to answer the question. If you don't know the answer, just say that you don't know. + Use two sentences maximum and keep the answer concise: + Question: {question} + Graph Context: {graph_context} + Answer: + """, + input_variables=["question", "graph_context"], +) + +``` +#### 3.2 生成回答 +``` +from langchain_core.output_parsers import StrOutputParser + +composite_chain = prompt | graph_llm |StrOutputParser() + +answer = composite_chain.invoke( + {"question": question, "graph_context": result} +) +print(answer) +``` +输出 + +``` +Marie Curie and Pierre Curie received the Nobel Prize. They were recognized for their groundbreaking work in radioactivaity. +``` + +### 4. 总结 +结合大模型和 openGauss AGEGraph 图数据库,我们可以快速进行知识图谱的生成、持久化以及检索,完成 GraphRAG 的搭建。此外,当前 openGauss 还支持标量、向量类型存储与检索,只需部署 openGauss 数据库,即可实现支持标量、向量、知识图谱多路召回的更强 RAG 系统。 diff --git a/content/docs-lite/zh/menu/index.md b/content/docs-lite/zh/menu/index.md index e27be8fd3..76bd9cfab 100644 --- a/content/docs-lite/zh/menu/index.md +++ b/content/docs-lite/zh/menu/index.md @@ -650,6 +650,7 @@ headless: true - [打破AI黑盒,拥抱开源力量:基于openGauss+DeepSeek的本地知识库,打造你的专属AI助手!]({{< relref "./docs/DataVec/openGauss-RAG实践.md" >}}) - [openGauss Datavec + Dify,快速搭建你的智能助手平台]({{< relref "./docs/DataVec/openGauss-Dify.md" >}}) - [Spring Boot集成openGauss DataVec实现向量化检索]({{< relref "./docs/DataVec/openGauss-Springboot.md" >}}) + - [openGauss AGEGraph + 大模型实现 GraphRAG,助力更强 RAG]({{< relref "./docs/DataVec/openGauss-AGEGraph.md" >}}) - [安全加固指南]({{< relref "./docs/SecHarden/secHarden.md" >}}) - [数据库加固概述]({{< relref "./docs/SecHarden/数据库加固概述.md" >}}) - [安全配置规范基线]({{< relref "./docs/SecHarden/安全配置规范基线.md" >}}) diff --git a/content/zh/docs/DataVec/DataVec-tutorials.md b/content/zh/docs/DataVec/DataVec-tutorials.md index fdf3cc46f..8932c25af 100644 --- a/content/zh/docs/DataVec/DataVec-tutorials.md +++ b/content/zh/docs/DataVec/DataVec-tutorials.md @@ -5,3 +5,4 @@ - [打破AI黑盒,拥抱开源力量:基于openGauss+DeepSeek的本地知识库,打造你的专属AI助手!](openGauss-RAG实践.md) - [openGauss DataVec + Dify, 快速搭建你的智能助手平台](openGauss-Dify.md) - [SpringBoot 集成 openGauss DataVec, 实现向量化检索](openGauss-Springboot.md) +- [openGauss AGEGraph + 大模型实现 GraphRAG,助力更强 RAG](openGauss-AGEGraph.md) diff --git a/content/zh/docs/DataVec/figures/openGauss-AGEGraph.png b/content/zh/docs/DataVec/figures/openGauss-AGEGraph.png new file mode 100644 index 0000000000000000000000000000000000000000..b2a00fb186c0c91df15ada70d4469017d10f423f GIT binary patch literal 32737 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/tcp opengauss-age + +``` +#### 1.2 AGE插件安装 + +``` +#进入openGauss容器中 253714c9c869为 CONTAINER ID +docker exec -it 253714c9c869 bash + +#切换到omm用户 +su omm + +#omm用户,连接数据库,默认使用omm数据库 +gsql -r + +#连接数据库后,omm数据库安装age插件 +create extension age; + +#退出数据库连接 +\q + +``` + +#### 1.3 python依赖安装 + +``` +pip install -U langchain_community langchain langgraph langchain-ollama langchain-experimental langchain-openai +``` +下载已适配的 langchain_community 仓库,操作如下: + +##### 1.3.1 下载适配好的langchain_community仓 +``` +git clone https://gitee.com/lin-qiang123/langchain.git +``` +##### 1.3.2 查找pip 安装的langchain_community位置 +``` +pip show langchain_community +``` +输出 + +``` +Name: langchain-community +Version: 0.3.20 +Summary: Community contributed LangChain integrations. +Home-page: +Author: +Author-email: +License: MIT +Location: c:\users\test\appdata\local\programs\python\python310\lib\site-packages #依赖库安装的位置 +Requires: numpy, PyYAML, aiohttp, tenacity, dataclasses-json, langchain, httpx-sse, SQLAlchemy, pydantic-settings, langchain-core, langsmith, requests +Required-by: langchain-experimental +``` + +##### 1.3.3 替换langchain-community +在git clone 下来的代码仓中,找到langchain\libs\community\langchain_community文件夹,复制并且覆盖到`Location`显示的文件夹中 + + +### 2. 利用 模型和 openGauss AGEGraph 快速构建知识图谱和检索 +本文使用百炼大模型,取得api-key,并且配置DASHSCOPE_API_KEY环境变量 +#### 2.1 初始化大模型 + +``` +from langchain_community.llms import Tongyi +import os + +os.environ["DASHSCOPE_API_KEY"] = "sk-**" +graph_llm =Tongyi(model="qwen-plus", temperature=0, base_url="https://dashscope.aliyuncs.com/compatible-mode/v1") + +``` +#### 2.2 通过大模型提取文本数据中的实体和关系 + + +``` +from langchain_core.documents import Document +from langchain_experimental.graph_transformers import LLMGraphTransformer + +#设置需要提取的实体类型和关系 +llm_transformer = LLMGraphTransformer( + llm=graph_llm, + allowed_nodes=["Person", "Organization", "Location", "Award", "ResearchField"], + allowed_relationships = ["SPOUSE", "AWARD", "FIELD_OF_RESEARCH", "WORKS_AT", "IN_LOCATION"], +) + +text = """ +Marie Curie, 7 November 1867 – 4 July 1934, was a Polish and naturalised-French physicist and chemist who conducted pioneering research on radioactivity. +She was the first woman to win a Nobel Prize, the first person to win a Nobel Prize twice, and the only person to win a Nobel Prize in two scientific fields. +Her husband, Pierre Curie, was a co-winner of her first Nobel Prize, making them the first-ever married couple to win the Nobel Prize and launching the Curie family legacy of five Nobel Prizes. +She was, in 1906, the first woman to become a professor at the University of Paris. +Also, Robin Williams. +""" + +# 将文本转化为图 +documents = [Document(page_content=text)] +graph_documents = llm_transformer.convert_to_graph_documents(documents) + + +print(f"Nodes from graph doc:{graph_documents[0].nodes}") +print(f"Relationships from graph doc:{graph_documents[0].relationships}") +``` +输出 + +``` +Nodes from graph doc:[Node(id='Nobel Prize', type='Award', properties={}), Node(id='University of Paris', type='Organization', properties={}), Node(id='Marie Curie', type='Person', properties={}), Node(id='radioactivity', type='ResearchField', properties={}), Node(id='Pierre Curie', type='Person', properties={})] +Relationships from graph doc:[Relationship(source=Node(id='Marie Curie', type='Person', properties={}), target=Node(id='radioactivity', type='ResearchField', properties={}), type='FIELD_OF_RESEARCH', properties={}), Relationship(source=Node(id='Marie Curie', type='Person', properties={}), target=Node(id='Nobel Prize', type='Award', properties={}), type='AWARD', properties={}), Relationship(source=Node(id='Marie Curie', type='Person', properties={}), target=Node(id='Nobel Prize', type='Award', properties={}), type='AWARD', properties={}), Relationship(source=Node(id='Marie Curie', type='Person', properties={}), target=Node(id='Pierre Curie', type='Person', properties={}), type='SPOUSE', properties={}), Relationship(source=Node(id='Pierre Curie', type='Person', properties={}), target=Node(id='Nobel Prize', type='Award', properties={}), type='AWARD', properties={}), Relationship(source=Node(id='Marie Curie', type='Person', properties={}), target=Node(id='University of Paris', type='Organization', properties={}), type='WORKS_AT', properties={})] +``` +#### 2.3 实例化 openGauss AGEGraph 客户端,持久化图数据 + +``` +from langchain_community.graphs.age_graph import AGEGraph + +conf = { + "database": "omm", + "user": "gaussdb", + "password": "YourPassoword", + "host": "Your IP", + "port": 8888, + "sslmode": "disable" +} +graph=AGEGraph(graph_name='graph_test1',conf=conf,create=True) +graph.add_graph_documents(graph_documents) +graph.refresh_schema() + +``` + +#### 2.4 大模型 Text2Cypher:提取问题关键词并生成图检索语句 + +通过增加提示词`cypher_prompt`,可以让大模型生成的图查询语句更加精准 +``` +from langchain_core.prompts import PromptTemplate +from langchain.chains import GraphCypherQAChain + +cypher_prompt = PromptTemplate( + template="""你是 AGE Cypher 查询生成的专家。 + 使用以下架构生成一个 Cypher 查询,以回答给定问题。 + 不要出现name和properties和cypher + + 架构: + {schema} + + 问题:{question} + + Cypher 查询:""", + input_variables=["schema", "question"], +) + +chain = GraphCypherQAChain.from_llm( + graph_llm, graph=graph, verbose=True, allow_dangerous_requests=True, cypher_validation=True, return_intermediate_steps=True,cypher_prompt=cypher_prompt +) + +question = "Who get Nobel Prize ?" +result = chain.invoke({"query": question}) +``` +输出 + +> Entering new GraphCypherQAChain chain... +Generated Cypher: +MATCH (p:Person)-[:AWARD]->(a:Award) +WHERE a.id = "Nobel Prize" +RETURN p.id +Full Context: +[{'p_id': 'Pierre Curie'}, {'p_id': 'Marie Curie'}] + +### 3. 大模型依据检索的图数据生成回答 + +#### 3.1 设置提示词 +``` +prompt = PromptTemplate( + template="""You are an assistant for question-answering tasks. + Use the following pieces of retrieved context from a graph database to answer the question. If you don't know the answer, just say that you don't know. + Use two sentences maximum and keep the answer concise: + Question: {question} + Graph Context: {graph_context} + Answer: + """, + input_variables=["question", "graph_context"], +) + +``` +#### 3.2 生成回答 +``` +from langchain_core.output_parsers import StrOutputParser + +composite_chain = prompt | graph_llm |StrOutputParser() + +answer = composite_chain.invoke( + {"question": question, "graph_context": result} +) +print(answer) +``` +输出 + +``` +Marie Curie and Pierre Curie received the Nobel Prize. They were recognized for their groundbreaking work in radioactivaity. +``` + +### 4. 总结 +结合大模型和 openGauss AGEGraph 图数据库,我们可以快速进行知识图谱的生成、持久化以及检索,完成 GraphRAG 的搭建。此外,当前 openGauss 还支持标量、向量类型存储与检索,只需部署 openGauss 数据库,即可实现支持标量、向量、知识图谱多路召回的更强 RAG 系统。 diff --git a/content/zh/menu/index.md b/content/zh/menu/index.md index 8ae385e31..398ffd468 100644 --- a/content/zh/menu/index.md +++ b/content/zh/menu/index.md @@ -935,6 +935,7 @@ headless: true - [打破AI黑盒,拥抱开源力量:基于openGauss+DeepSeek的本地知识库,打造你的专属AI助手!]({{< relref "./docs/DataVec/openGauss-RAG实践.md" >}}) - [openGauss Datavec + Dify,快速搭建你的智能助手平台]({{< relref "./docs/DataVec/openGauss-Dify.md" >}}) - [Spring Boot集成openGauss DataVec实现向量化检索]({{< relref "./docs/DataVec/openGauss-Springboot.md" >}}) + - [openGauss AGEGraph + 大模型实现 GraphRAG,助力更强 RAG]({{< relref "./docs/DataVec/openGauss-AGEGraph.md" >}}) - [AI特性指南]({{< relref "./docs/AIFeatureGuide/AI特性.md" >}}) - [AI4DB: 数据库自治运维]({{< relref "./docs/AIFeatureGuide/AI4DB-数据库自治运维.md" >}}) - [DBMind模式说明]({{< relref "./docs/AIFeatureGuide/DBMind模式说明.md" >}}) -- Gitee