跳转到主要内容

基于图数据库支持的知识图的对话系统原型。

项目描述

Siwi语音助手

Siwi (/ˈsɪwi/) 是一个基于图数据库支持的知识图的对话系统原型。

目前,它是一个使用Nebula Graph的示例/样本数据集的KG(知识图谱)驱动的(非通用目的)对话机器人的演示。

提示:现在您可以在不安装的情况下在线玩转图!

Nebula Playground | Nebula Playground - 中国大陆

支持的查询

关系:

  • 姚明和湖人队之间是什么关系?
  • 姚明和湖人队是如何联系的?

服务:

  • 姚明为哪支球队效力?

友谊:

  • 蒂姆·邓肯关注谁?
  • 姚明的朋友是谁?

部署和尝试

您可以从这里从头开始尝试: https://katacoda.com/wey/scenarios/siwi-kgqa

它是如何工作的?

这是在知识图上构建的一个特定领域/单一用途聊天机器人的最简单管道之一。

后端

backend-demo

后端(Siwi API)是一个基于Flask的API服务器

  • Flask API服务器接收HTTP POST中的问题,并调用聊天机器人API。

  • 在聊天机器人API部分有分类器(语义解析、意图匹配、槽填充)和问题执行者(调用相应动作以使用意图和槽查询知识图)。

  • 知识图谱建立在开源图数据库之上:Nebula Graph

前端

demo

前端是一个VueJS单页应用程序(SPA)

  • 我重新使用了Vue Bot UI来展示聊天窗口,支持键盘输入。
  • 此外,利用Chrome的Web Speech API,引入了一个监听人类语音的按钮。

查询流程

┌────────────────┬──────────────────────────────────────┐
│                │                                      │
│                │  Speech                              │
│     ┌──────────▼──────────┐                           │
│     │            Frontend │   Siwi, /ˈsɪwi/           │
│     │ Web_Speech_API      │   A PoC of                │
│     │                     │   Dialog System           │
│     │ Vue.JS              │   With Graph Database     │
│     │                     │   Backed Knowledge Graph  │
│     └──────────┬──────────┘                           │
│                │  Sentence                            │
│                │                                      │
│   ┌────────────┼──────────────────────────────┐       │
│   │            │                              │       │
│   │            │              Backend         │       │
│   │ ┌──────────▼──────────┐                   │       │
│   │ │ Web API, Flask      │   ./app/          │       │
│   │ └──────────┬──────────┘                   │       │
│   │            │  Sentence    ./bot/          │       │
│   │ ┌──────────▼──────────┐                   │       │
│   │ │                     │                   │       │
│   │ │ Intent matching,    │   ./bot/classifier│       │
│   │ │ Symentic Processing │                   │       │
│   │ │                     │                   │       │
│   │ └──────────┬──────────┘                   │       │
│   │            │  Intent, Entities            │       │
│   │ ┌──────────▼──────────┐                   │       │
│   │ │                     │                   │       │
│   │ │ Intent Actor        │   ./bot/actions   │       │
│   │ │                     │                   │       │
│   └─┴──────────┬──────────┴───────────────────┘       │
│                │  Graph Query                         │
│     ┌──────────▼──────────┐                           │
│     │                     │                           │
│     │ Graph Database      │    Nebula Graph           │
│     │                     │                           │
│     └─────────────────────┘                           │
│                                                       │
│                                                       │
│                                                       │
└───────────────────────────────────────────────────────┘

源代码树

.
├── README.md
├── src
│   ├── siwi                        # Siwi-API Backend      ├── app                     # Web Server, take HTTP requests and calls Bot API      └── bot                     # Bot API          ├── actions             # Take Intent, Slots, Query Knowledge Graph here          ├── bot                 # Entrypoint of the Bot API          ├── classifier          # Symentic Parsing, Intent Matching, Slot Filling          └── test                # Example Data Source as equivalent/mocked module   └── siwi_frontend               # Browser End       ├── README.md
│       ├── package.json
│       └── src
│           ├── App.vue             # Listening to user and pass Questions to Siwi-API           └── main.js
└── wsgi.py

手动运行组件

图数据库

后端依赖于Nebula Graph,一个开源的分布式图数据库。

一行代码安装Nebula Graph

curl -fsSL nebula-up.siwei.io/install.sh | bash

加载basketballplayer数据集

~/.nebula-up/console.sh
nebula-console -addr graphd -port 9669 -user root -p nebula -e ":play basketballplayer"

后端

安装并运行。

# Install siwi backend
python3 -m build

# Configure Nebula Graph Endpoint
export NG_ENDPOINTS=127.0.0.1:9669

# Run Backend API server
gunicorn --bind :5000 wsgi --workers 1 --threads 1 --timeout 60

对于OpenFunction/ KNative

docker build -t weygu/siwi-api .
docker run --rm --name siwi-api \
     --env=PORT=5000 \
     --env=NG_ENDPOINTS=127.0.0.1:9669 \
     --net=host \
     weygu/siwi-api

尝试Web API

$ curl -s --header "Content-Type: application/json" \
       --request POST \
       --data '{"question": "What is the relationship between Yao Ming and Lakers?"}' \
       http://192.168.8.128:5000/query | jq

{
  "answer": "There are at least 23 relations between Yao Ming and Lakers, one relation path is: Yao Ming follows Shaquille O'Neal serves Lakers."
}

调用Bot Python API

from nebula3.gclient.net import ConnectionPool
from nebula3.Config import Config

# define a config
config = Config()
config.max_connection_pool_size = 10
# init connection pool
connection_pool = ConnectionPool()
# if the given servers are ok, return true, else return false
ok = connection_pool.init([('127.0.0.1', 9669)], config)

# import siwi bot
from siwi.bot import bot

# instantiate a bot
b = bot.SiwiBot(connection_pool)

# make the question query
b.query("Which team had Jonathon Simmons served?")

然后响应将像这样

In [4]: b.query("Which team had Jonathon Simmons serv
   ...: ed?")

[DEBUG] ServeAction intent: {'entities': {'Jonathon Simmons': 'player'}, 'intents': ('serve',)}

[DEBUG] query for RelationshipAction:
	USE basketballplayer;
  MATCH p=(v)-[e:serve*1]->(v1) WHERE id(v) == "player112"
  RETURN p LIMIT 100;

[2021-07-02 02:59:36,392]:Get connection to ('127.0.0.1', 9669)

Out[4]: 'Jonathon Simmons had served 3 teams. Spurs from 2015 to 2015; 76ers from 2019 to 2019; Magic from 2017 to 2017; '

前端

参考siwi_frontend

使用K8s + OpenFunction部署

 ┌─────────────────────────────┐
 │ kind: Ingress               │     ┌───────────────────┐
 │   path: /                   │     │ Pod               │
 │    -> siwi-frontend     ────┼─────┤  siwi-frontend    │
 │                             │     │                   │
 │                             │     └───────────────────┘
 │                             │
 │   path: /query              │     ┌───────────────────────────────────┐
 │    -> siwi-api          ────┼─────┤ KNative Service                   │
 │       KNative Serving       │     │  serving-xxxx                     │
 │                             │     │                                   │
 │                             │     │ apiVersion: serving.knative.dev/v1│
 │                             │     │ kind: Service                     │
 └─────────────────────────────┘     └─────────┬─────────────────────────┘
                                               │
                                               └────────────┐
                                                            │
 ┌───────────────────────────────────────────────────────┐  │
 │apiVersion: core.openfunction.io/v1alpha1              │  │
 │kind: Function                                         │  │
 │spec:                                                  │  │
 │  version: "v1.0.0"                                    │  │
 │  image: "weygu/siwi-api:latest"                       │  │
 │  imageCredentials:                                    │  │
 │    name: push-secret                                  │  │
 │  port: 8080                                           │  │
 │  build:                                               │  │
 │    builder: openfunction/builder:v1                   │  │
 │    env:                                               │  │
 │      FUNC_NAME: "siwi_api"                            │  │
 │      FUNC_TYPE: "http"                                │  │
 │      FUNC_SRC: "main.py"                              │  │
 │    srcRepo:                                           │  │
 │      url: "https://github.com/wey-gu/nebula-siwi.git" │  │
 │      sourceSubPath: "src"                             │  │
 │  serving:                                             │  │
 │    runtime: Knative  ─────────────────────────────────┼──┘
 │    params:                                            │
 │      NG_ENDPOINTS: "NEBULA_GRAPH_ENDPOINT"            │
 │    template:                          │               │
 │      containers:                      │               │
 │        - name: function               │               │
 │          imagePullPolicy: Always      │               │
 └───────────────────────────────────────┼───────────────┘
                                         │
                              ┌──────────┘
                              │
 ┌────────────────────────────┴───────────────────────────┐
 │apiVersion:lapps.nebula-graph.io/v1alpha1               │
 │kind: NebulaCluster                                     │
 │spec:                                                   │
 │  graphd:                                               │
 │    config:                                             │
 │      system_memory_high_watermark_ratio: "1.0"         │
 │    image: vesoft/nebula-graphd                         │
 │    replicas: 1                                         │
 │...                                                     │
 └────────────────────────────────────────────────────────┘

假设我们已经安装了OpenFunctions的k8s

运行它!

在KubeSphere上使用kubesphere-all-in-one nebula安装程序安装Nebula Graph

curl -sL nebula-kind.siwei.io/install-ks-1.sh | bash

获取Nebula Graph NodePort

NEBULA_GRAPH_ENDPOINT=$(kubectl get svc nebula-graphd-svc-nodeport -o yaml -o jsonpath='{.spec.clusterIP}:{.spec.ports[0].port}')
echo $NEBULA_GRAPH_ENDPOINT

将数据集加载到nebula集群中

wget https://docs.nebula-graph.io/2.0/basketballplayer-2.X.ngql

~/.nebula-kind/bin/console -u root -p password --address=<nebula-graphd-svc-nodeport> --port=32669 -f basketballplayer-2.X.ngql

创建由Openfunction驱动的siwi-api

cat siwi-api-function.yaml | sed "s/NEBULA_GRAPH_ENDPOINT/$NEBULA_GRAPH_ENDPOINT/g" | kubectl apply -f -

获取函数nebula-siwi和KNative服务

kubectl get functions nebula-siwi

FUNCTION=$(kubectl get functions nebula-siwi -o go-template='{{.status.serving.resourceRef}}')

kubectl get ksvc -l openfunction.io/serving=$FUNCTION

KSVC=$(kubectl get ksvc -l openfunction.io/serving=$FUNCTION -o=jsonpath='{.items[0].metadata.name}')

kubectl get revision -l serving.knative.dev/service=$KSVC

REVISION=$(kubectl get revision -l serving.knative.dev/service=$KSVC -o=jsonpath='{.items[0].metadata.name}')

echo $REVISION

验证函数正常工作

curl -s --header "Content-Type: application/json" \
     --request POST \
     --data '{"question": "What is the relationship between Yao Ming and Lakers ?"}' \
     $(kubectl get ksvc -l openfunction.io/serving=$FUNCTION -o=jsonpath='{.items[0].status.url}')/query

在K8s上创建siwi-app资源

cat siwi-app.yaml | sed "s/REVISION/$REVISION/g" | kubectl apply -f -

通过ingress验证函数正常工作

这里使用了nodeport,http端口为31059作为ingress控制器端点。

curl -s --header "Content-Type: application/json" \
     --request POST \
     --data '{"question": "how does Tim Duncan and Lakers connected?"}' \
     demo-siwi.local:31059/query

验证前端

curl $(kubectl get svc -l app=siwi -o=jsonpath='{.items[0].spec.clusterIP}')

验证位于ingress之后的前端

curl demo-siwi.local:31059

获取siwi-app中的所有资源

kubectl get service,pod,ingress,function -l app=siwi

它应该是这样的

[root@wey nebula-siwi]# kubectl get service,pod,ingress,function -l app=siwi
NAME                         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/siwi-frontend-file   ClusterIP   10.233.60.81   <none>        80/TCP    64m

NAME                     READY   STATUS    RESTARTS   AGE
pod/siwi-frontend-file   1/1     Running   0          64m

NAME                                     CLASS    HOSTS             ADDRESS   PORTS   AGE
ingress.networking.k8s.io/siwi-service   <none>   demo-siwi.local             80      59m

NAME                                        BUILDSTATE   SERVINGSTATE   BUILDER         SERVING         AGE
function.core.openfunction.io/nebula-siwi   Succeeded    Running        builder-sbfz6   serving-vvjvl   26h
[root@wey nebula-siwi]# kubectl get service,pod,ingress,function -l app=siwi
NAME                         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/siwi-frontend-file   ClusterIP   10.233.60.81   <none>        80/TCP    65m

NAME                     READY   STATUS    RESTARTS   AGE
pod/siwi-frontend-file   1/1     Running   0          65m

NAME                                     CLASS    HOSTS             ADDRESS   PORTS   AGE
ingress.networking.k8s.io/siwi-service   <none>   demo-siwi.local             80      59m

NAME                                        BUILDSTATE   SERVINGSTATE   BUILDER         SERVING         AGE
function.core.openfunction.io/nebula-siwi   Succeeded    Running        builder-sbfz6   serving-vvjvl   26h

如何构建镜像

docker build -t weygu/siwi-frontend . -f Dockerfile.froentend
docker push weygu/siwi-frontend

进一步工作

  • 使用NBA-API来解决未定义模式的问题
  • 封装和管理会话,而不是每次请求获取和释放会话,这实际上很昂贵。
  • 使用NLP方法实现适当的语义解析、意图匹配、槽填充
  • 构建图以帮助意图匹配,特别是对于通用机器人
  • 使用更大的数据集,例如来自wyattowalsh/basketball

感谢上游项目 ❤️

后端

前端

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分发

siwi-0.3.2.tar.gz (16.9 kB 查看哈希值)

上传于 源码

构建分发

siwi-0.3.2-py3-none-any.whl (12.9 kB 查看哈希值)

上传于 Python 3

支持