Skip to content

Commit

Permalink
[ISSUE-255] Support natural language graph analytics by LLM
Browse files Browse the repository at this point in the history
  • Loading branch information
652053395 authored Mar 27, 2024
1 parent 246457e commit 5cfc4a8
Show file tree
Hide file tree
Showing 71 changed files with 5,444 additions and 62 deletions.
1,789 changes: 1,789 additions & 0 deletions data/geaflow-dsl-finetuning.jsonl

Large diffs are not rendered by default.

25 changes: 25 additions & 0 deletions docs/docs-cn/application-development/dsl/chat/chat_guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# GQL大模型语法提示手册
本手册列出了GQL常见的语法点以及参考的提示方法,用户可参考提问示例让模型生成对应的语法的GQL语句。

| 语法 | 提问示例 | 结果 |
| --- | --- | --- |
| 查找点 | 请找出的类型为person**的点** | match(a:person) return a |
| 查找边 | 返回图中所有的标签为knows**的边** | match(a)-[e:knows]->(b) return e |
| 查找关系 | 查询10个属于北京的大学<br />找出5个和小张老师**有关系**的学生 | match(a:city where a.name = '北京')<-[:belong]-(b:university) return b limit 10<br />match(a:teacher where a.name='小张')-[e]-(b:student) return b limit 5 |
| 查找多度关系 | 查找小王同学的朋友认识的人<br /><br />请帮我找出和标签为大学的点有拥有关系的部门,并且和这些部门有拥有关系的学生,并且和这些学生有选择关系的课程<br /><br />请查找腾讯和谷歌公司共同创建的软件的名称,返回5个。 | match(a:student where a.name = '小王')-[e:friend]->(b)-[e2:knows]->(c:person) return c<br /><br />match(a:university)-[e:has]->(b:department)-[e2:has]->(c:student)-[e3:selects]->(d:course) return d<br /><br />match(a:company where a.name='腾讯')-[e:creates]->(b:software)<-[e2:creates]-(c:company where c.name='谷歌') return b.name limit 5 |
| Loop | 查询从person张思琪出发,经过类型为支付的边,**走2到4度到达的点** | match(a:person where a.name='张思琪')-[e:pay]->{2,4}(b:person) return b |
| Loop(环) | 找出与person李红有knows关系的**3跳以内的环** | match(a:person where name = '李红')-[e:knows]->{1,2}(b)->(a) return a.id, b.id as b_id<br /> |
| 过滤条件 | 找出小红认识的年龄大于20,工资大于5000的人<br /><br /><br />请帮我找出10个性别不是famale且身高小于160,或id大于5的节点 | match(a:person where a.name='小红')-[e:knows]->(b:person where b.age > 20 and b.salary > 5000) return b<br /><br />match(a where (a.gender <> 'female' and a.height < 160) or a.id > 5) return a limit 10 |
| Let单值 | 查询蚂蚁集团创造的软件, ****软件的minPrice**等于**软件的价格的最小值, 返回公司的id, 软件的minPrice | match(a:company where a.name = '蚂蚁集团')-[e:creates]->(b:software) let b.minPrice = MIN(b.price) return a.id, b.minPrice |
| Let子查询 | 请帮我查找公司蚂蚁集团雇佣的person, ****这个person的countSalary**的值等于**认识他的人的薪资的和, 再查找他购买的软件<br /><br />给出id为10的城市所属于的国家, 并将国家有关的公司的人数的平均值**赋值**给国家的avgCnt | match(a:company where a.name = '蚂蚁集团')-[e:employee]->(b:person) let b.countSalary = SUM((b:person)<-[e2:knows]-(c:person) => c.salary) match(b:person)-[e3:buy]->(d:software) return b.countSalary, d<br /><br />match(a:city where id = '10')-[e:belong]->(b:country)<-[e2:belong]-(c:company) let b.avgCnt = AVG(c.peopleNumber) return b |
| 函数调用 | **调用SSSP函数**,以'arg1', 10**作为输入**,返回id, distance | match(a:person) call sssp(a, 10) yield (id, distance) return id, distance |
| order | 返回公司创造的软件,并根据公司的规格从大到小、软件的价格**从小到大排序** | match(a:company)-[e:creates]->(b:software) return a.scale,b.price order by a.scale desc, b.price asc |
| group by | 找出小红认识的人,**根据**这些人的性别**分组**,返回工资的最大值<br /><br />帮我找出与北京大学有关联的公司,返回公司****规模**进行分组**的人数的平均值 | match(a:person where person.name = '小红')-[e:knows]->(b:person) return MAX(b.salary) group by b.gender<br /><br />match(a:university where a.name='北京大学')-[e]-(b:company) return AVG(b.peopleNumber) group by b.scale |
| join | 找出郑伟喜欢的所有人,以及认识郑伟的所有人,并将它们**一起返回**<br /><br />请帮我找出和person alice有关联的学校,**称为X**,再帮我找出**和这个X有关联**的其他公司,以及和X有关联的person | match(a:person where a.name = '郑伟')-[e:likes]->(b:person),(a:person where a.name = '郑伟')<-[e2:knows]-(c:person) return a, b, c<br /><br />match(a:person where a.name = 'alice')-[e]-(b:school), (b:school)-[e2]-(c:company),(b:school)-[e3]-(d:person) return a, b, c, d |
| 带图的schema单条查询<br />**(在Console中开启“附带图schema”开关会自动拼接,不需要用户自己输入**) | 使用这个图:CREATE GRAPH g ( Vertex film ( id int ID, name varchar, category varchar, value int ), Vertex cinema ( id int ID, name varchar, address varchar, size int ), Vertex person ( id int ID, name varchar, age int, gender varchar, height int, salary int ), Vertex comment ( id int ID, name varchar, createTime bigint, wordCount int ), Vertex tag ( id int ID, name varchar, value int ), Edge person_likes_comment ( srcId int FROM person SOURCE ID, targetId int FROM comment DESTINATION ID, weight double, f0 int, f1 boolean ), Edge cinema_releases_film ( srcId int FROM cinema SOURCE ID, targetId int FROM film DESTINATION ID, weight double, f0 int, f1 boolean ), Edge person_watch_film ( srcId int FROM person SOURCE ID, targetId int FROM film DESTINATION ID, weight double, f0 int, f1 boolean, timeStamp bigint ), Edge film_has_tag ( srcId int FROM film SOURCE ID, targetId int FROM tag DESTINATION ID, weight double, f0 int, f1 boolean ), Edge person_creates_comment ( srcId int FROM person SOURCE ID, targetId int FROM comment DESTINATION ID, weight double, f0 int, f1 boolean, timeStamp bigint ), Edge comment_belong_film ( srcId int FROM comment SOURCE ID, targetId int FROM film DESTINATION ID, weight double, f0 int, f1 boolean ));找出和person孙梅有person_creates_comment关系的comment,以及和person孙建聪有person_likes_comment关系的comment,将它们都返回 | atch(a:person where a.name = '孙梅')-[e:person_creates_comment]->(b:comment),(c:person where c.name = '孙建聪')-[e2:person_likes_comment]->(d:comment)return a, b, c, d |
| 带图的schema多条查询 | 使用这个图:CREATE GRAPH g ( Vertex book ( id int ID, name varchar, id int ID, name varchar, category varchar, price int, wordCount int, createTime bigint ), Vertex publisher ( id int ID, name varchar, age int, gender varchar, height int, salary int ), Vertex reader ( id int ID, name varchar, age int, gender varchar, height int, salary int ), Vertex author ( id int ID, name varchar, age int, gender varchar, height int, salary int ), Edge author_write_book ( srcId int FROM author SOURCE ID, targetId int FROM book DESTINATION ID, weight double, f0 int, f1 boolean, timeStamp bigint ), Edge publisher_publish_book ( srcId int FROM publisher SOURCE ID, targetId int FROM book DESTINATION ID, weight double, f0 int, f1 boolean, timeStamp bigint ), Edge book_refers_book ( srcId int FROM book SOURCE ID, targetId int FROM book DESTINATION ID, weight double, f0 int, f1 boolean ), Edge reader_likes_book ( srcId int FROM reader SOURCE ID, targetId int FROM book DESTINATION ID, weight double, f0 int, f1 boolean ), Edge author_knows_author ( srcId int FROM author SOURCE ID, targetId int FROM author DESTINATION ID, weight double, f0 int, f1 boolean ));执行以下4个查询:1: 找出被作家黄建聪认识的作家;2: 返回源点标签为作家,目标点标签为作家,标签为author_knows_author的边;3: 请帮我查找所有与book计算机网络有关系的book的id;4: 请帮我查找152个与何雪和张建聪都存在关系的书节点; | 查询语句为:1: match(a:author)<-[e:author_knows_author]-(b:author where b.name='黄建聪') return a, b;2: match(a:author)-[e:author_knows_author]->(b:author) return e;3: match(a:book where a.name='计算机网络')-[e]-(b:book) return b.id;4: match(a where a.name='何雪')-[e]->(b:book)<-[e2]-(c where c.name='张建聪') return b limit 152; |





80 changes: 80 additions & 0 deletions docs/docs-cn/deploy/install_llm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
用户可以在本地完成大模型的服务化部署,以下步骤描述了从下载预训练模型,服务化部署和调试的整个过程。用户机器确保已安装Docker,可访问大模型存储库。

## 步骤1:下载大模型文件

我们已将预训练好的大模型文件,上传至[Hugging Face仓库](https://huggingface.co/tugraph/CodeLlama-7b-GQL-hf),下载模型文件后解压到本地。下载完成后,解压模型文件到指定的本地目录,如 /home/huggingface。
![hugging](../../static/img/llm_hugging_face.png)

## 步骤2:准备 Docker 容器环境
1. 在终端运行以下命令下载模型服务化所需的 Docker 镜像:

```
docker pull tugraph/llam_infer_service:0.0.1
//使用以下命令来验证镜像是否成功下载
docker images
```

2. 运行以下命令启动Docker容器:

```
docker run -it --name ${容器名称} -v ${本地模型路径}:${容器模型路径} -p ${本地端口}:${容器服务化端口} -d ${镜像名}
//例如
docker run -it --name my-model-container -v /home/huggingface:/opt/huggingface -p 8000:8000 -d llama_inference_server:v1
// 检查容器是否正常运行
docker ps
```

在这里,我们将容器的 8000 端口映射到本地机器的 8000 端口,将本地模型(/home/huggingface)所在目录挂载到容器的路径(/opt/huggingface),并将容器名称设置为 my-model-container。

## 步骤3:模型服务化部署
1. 模型转换
```
//进入上述刚创建好的容器
docker exec -it ${container_id} bash
//执行如下命令
cd /opt/llama_cpp
python3 ./convert.py ${容器模型路径}
```
执行完成后, 会在容器模型路径下生成前缀为ggml-model的文件
![undefined](../../static/img/llm_ggml_model.png)

2. 模型量化(可选)
以llam2-7B模型为例:通过convert.py默认转换后的模型精度为F16,模型大小为13.0GB。如果当前机器资源无法满足这么大的模型推理,可通过./quantize对转换后的模型进一步量化。
```
// 如下所示 q4_0即将原始模型量化为int4,模型大小压缩至3.5GB;
// 其它参数类似
cd /opt/llama_cpp
./quantize 默认生成的F16模型路径 量化后模型路径 q4_0
```
以下是量化后模型的大小和推理速度等参考指标:
![undefined](../../static/img/llm_quantization_table.png)

3. 模型服务化
通过以下命令,将上述生成的模型进行服务化的部署,通过参数指定服务绑定的地址和端口:
```
// ./server -h 可查看参数详情
// ${ggml-model...文件}为生成的ggml-model前缀的文件名
cd /opt/llama_cpp
./server --host ${ip} --port ${port} -m ${容器模型路径}/${ggml-model...文件} -c 4096
//例如
./server --host 0.0.0.0 --port 8000 -m /opt/huggingface/ggml-model-f16.gguf -c 4096
```

4. 调试服务
向服务地址发送http请求,其中"prompt"为查询的语句, 在返回的"content"中则是推理结果。

```
curl --request POST \
--url http://127.0.0.1:8000/completion \
--header "Content-Type: application/json" \
--data '{"prompt": "请返回小红的10个年龄大于20的朋友","n_predict": 128}'
```
如下是服务化部署后的模型推理结果:
![undefined](../../static/img/llm_chat_result.png)

83 changes: 83 additions & 0 deletions docs/docs-en/deploy/install_llm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
The users have the capability to locally deploy extensive models as a service. The complete process, encompassing downloading pre-trained models, deploying them as a service, and debugging, is described in the following steps. It is essential for the user's machine to have Docker installed and be granted access to the repository containing these large models.

## Step 1: Download the model file
The pre-trained large model file has been uploaded to the [Hugging Face repository](https://huggingface.co/tugraph/CodeLlama-7b-GQL-hf). Please proceed with downloading and locally unzipping the model file.
![hugging](../../static/img/llm_hugging_face.png)

## Step 2: Prepare the Docker container environment
1. Run the following command on the terminal to download the Docker image required for model servicing:

```
docker pull tugraph/llam_infer_service:0.0.1
// Use the following command to verify that the image was successfully downloaded
docker images
```

2. Run the following command to start the Docker container:

```
docker run -it --name ${Container name} -v ${Local model path}:${Container model path} -p ${Local port}:${Container service port} -d ${Image name}
// Such as
docker run -it --name my-model-container -v /home/huggingface:/opt/huggingface -p 8000:8000 -d llama_inference_server:v1
// Check whether the container is running properly
docker ps
```

Here, we map the container's port 8000 to the local machine's port 8000, mount the directory where the local model (/home/huggingface) resides to the container's path (/opt/huggingface), and set the container name to my-model-container.

## Step 3: Model service deployment
1. Model transformation
```
// Enter the container you just created
docker exec -it ${container_id} bash
// Execute the following command
cd /opt/llama_cpp
python3 ./convert.py ${Container model path}
```
When the execution is complete, a file with the prefix ggml-model is generated under the container model path.
![undefined](../../static/img/llm_ggml_model.png)

2. Model quantization (optional)
Take the llam2-7B model as an example: By default, the accuracy of the model converted by convert.py is F16 and the model size is 13.0GB. If the current machine resources cannot satisfy such a large model inference, the converted model can be further quantized by./quantize.

```
// As shown below, q4_0 quantizes the original model to int4 and compresses the model size to 3.5GB
cd /opt/llama_cpp
./quantize ${Default generated F16 model path} ${Quantized model path} q4_0
```
The following are reference indicators such as the size and reasoning speed of the quantized model:
![undefined](../../static/img/llm_quantization_table.png)

3. Model servicing
Run the following command to deploy the above generated model as a service, and specify the address and port of the service binding through the parameters:
```
// ./server -h. You can view parameter details
// ${ggml-model...file} The file name prefixes the generated ggml-model
cd /opt/llama_cpp
./server --host ${ip} --port ${port} -m ${Container model path}/${ggml-model...file} -c 4096
// Such as
./server --host 0.0.0.0 --port 8000 -m /opt/huggingface/ggml-model-f16.gguf -c 4096
```

4. Debugging service
Send an http request to the service address, where "prompt" is the query statement and "content" is the inference result.

```
curl --request POST \
--url http://127.0.0.1:8000/completion \
--header "Content-Type: application/json" \
--data '{"prompt": "请返回小红的10个年龄大于20的朋友","n_predict": 128}'
```
Debugging service
The following is the model inference result after service deployment:
![undefined](../../static/img/llm_chat_result.png)


Binary file added docs/static/img/llm_chat_result.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/img/llm_ggml_model.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/img/llm_hugging_face.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/img/llm_quantization_table.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright 2023 AntGroup CO., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*/

package com.antgroup.geaflow.console.biz.shared;


import com.antgroup.geaflow.console.biz.shared.view.ChatView;
import com.antgroup.geaflow.console.common.dal.model.ChatSearch;

public interface ChatManager extends IdManager<ChatView, ChatSearch> {

String callSync(ChatView chatView, boolean record, boolean withSchema);

String callASync(ChatView chatView, boolean withSchema);

boolean dropByJobId(String jobId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright 2023 AntGroup CO., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*/

package com.antgroup.geaflow.console.biz.shared;


import com.antgroup.geaflow.console.biz.shared.view.LLMView;
import com.antgroup.geaflow.console.common.dal.model.LLMSearch;
import com.antgroup.geaflow.console.common.util.type.GeaflowLLMType;
import java.util.List;

public interface LLMManager extends NameManager<LLMView, LLMSearch> {

List<GeaflowLLMType> getLLMTypes();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2023 AntGroup CO., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*/

package com.antgroup.geaflow.console.biz.shared.convert;

import com.antgroup.geaflow.console.biz.shared.view.ChatView;
import com.antgroup.geaflow.console.core.model.llm.GeaflowChat;
import org.springframework.stereotype.Component;

@Component
public class ChatViewConverter extends IdViewConverter<GeaflowChat, ChatView> {

@Override
public void merge(ChatView view, ChatView updateView) {
super.merge(view, updateView);
}

@Override
protected ChatView modelToView(GeaflowChat model) {
ChatView view = super.modelToView(model);
view.setModelId(model.getModelId());
view.setAnswer(model.getAnswer());
view.setPrompt(model.getPrompt());
view.setStatus(model.getStatus());
view.setJobId(model.getJobId());
return view;
}

@Override
protected GeaflowChat viewToModel(ChatView view) {
GeaflowChat model = super.viewToModel(view);
model.setModelId(view.getModelId());
model.setAnswer(view.getAnswer());
model.setPrompt(view.getPrompt());
model.setStatus(view.getStatus());
model.setJobId(view.getJobId());
return model;
}

public GeaflowChat convert(ChatView view) {
return viewToModel(view);
}

}
Loading

0 comments on commit 5cfc4a8

Please sign in to comment.