V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
websong188
V2EX  ›  Go 编程语言

golang 结合 cobra 使用 chatgpt qdrant 实现 ai 知识库 cli

  •  1
     
  •   websong188 · 2023-09-22 00:59:52 +08:00 · 1164 次点击
    这是一个创建于 457 天前的主题,其中的信息可能已经有所发展或是发生改变。

    golang 结合 cobra 使用 chatgpt qdrant 实现 ai 知识库 cli

    流程

    1. 将数据集 通过 openai embedding 得到向量+组装 payload,存入 qdrant
    2. 用户进行问题搜索,通过 openai embedding 得到向量,从 qdrant 中搜索相似度大于 0.8 的数据
    3. 从 qdrant 中取出数据得到参考答案
    4. 将问题标题+参考答案,组装成 promot 向 gpt 进行提问,得到偏向于 已有知识库设定的扩展知识回答

    kabi 知识库的导入和搜索

    仓库地址:https://github.com/webws/embedding-knowledge-base

    kabi 是使用 golang 基于 openai chatgpt embedding + qdrant 实现知识库的导入和问答

    ❯ kabi -h
    a local knowledge base, based on chatgpt and qdrant
    
    usage:
      kbai [flags]
      kbai [command]
    
    available commands:
      completion  generate the autocompletion script for the specified shell
      help        help about any command
      import      import data to vector database
      search      ask the knowledge base example: kbai ask --msg 'first, the chicken or the egg'
    
    flags:
          --apikey string       openai apikey:default from env apikey
          --collection string   qdrant collection name default: kubernetes (default "kubernetes")
      -h, --help                help for kbai
          --proxy string        http client proxy default:socks5://127.0.0.1:1080  (default "socks5://127.0.0.1:1080")
          --qdrant string       qdrant address default: 127.0.0.1:6334 (default "127.0.0.1:6334")
          --vectorsize uint     qdrant vector size default: 1536 (default 1536)
    
    use "kbai [command] --help" for more information about a command.
    

    启动向量数据库

    qdrant 是一个开源的向量搜索引擎,支持多种向量距离计算方式

    docker 运行 qdrant

    docker run --rm -p 6334:6334 qdrant/qdrant
    

    kbai 库导入数据到知识库

    clone 源码运行(后续提供二进制文件)

    git clone https://github.com/webws/embedding-knowledge-base.git
    
    cd ./embedding-knowledge-base
    

    这里使用的测试数据是 k8s 相关的知识库,真实数据需自己准备

    1.设置 openai apikey

    export apikey=xxx
    

    2.导入知识库(源码运行)

    go run ./ import --datafile ./example/data.json
    

    data.json 数据格式如下,为 真实数据需自己准备

    [
        {
            "questions": "这是问题",
            "answers": "这是答案"
        },
    ]
    

    说明:

    默认的 代理 是 "socks5://127.0.0.1:1080" 自定义 可使用 --proxy 指定
    

    kbai 搜索数据

    搜索问题(源码执行)

     go run ./ search --msg "网关是什么"
    

    回答

    the answer to the knowledge base:
    在 kubernetes 中,网关通常指的是 ingress (入 口)资源对象。ingress 是一种 kubernetes api 对象,用于配置和管理集群中的 http 和 https 流量入口。它充当了从集群外部访问集群内部服务的入口点
    
    results of chatgpt answers  with reference answers:
    ,同时提供负载均衡、ssl/tls 终止和基于域名的路由等功能。ingress 资源对象定义了一组规则,这些规则指定了通过特定 http 路径或主机名将请求路由到后端服务的方式。可以使用不同的 ingress 控制器实现这些规则,如 nginx 、traefik 等。这样就可以在集群中创建多个 ingress 资源对象来管理不同的流量入口。
    
    only chatgpt answers:
    网关是一种网络设备,用于连接两个或多个不同类型的网络,以便实现数据以不同协议进行传递和转换。网关起到了连接不同网络之间的桥梁作用,将两个或多个网络互相连接起来,并负责数据的路由和转发。网关可以是硬件设备,如路由器,也可以是软件程序,如互联网网关。网关通常用于连接本地网络与互联网,使得局域网中的计算机能够访问互联网上的资源。除了连接不同网络的功能,网关还可以实现安全性、负载均衡、数据过滤等功能。
    
    1. 第一个是知识库的回答(the answer to the knowledge base):
    2. 第二个 是结合知识库 chatgpt 的回答(results of chatgpt answers with reference answers)
    3. 第三个 仅 chatgpt 回答

    可以看出 直接问 chatgpt,得到的答案可能跟 k8s 无关,结合 k8s 本地知识库,可以让回答偏向 数据集设定的主题

    如果直接搜索 与知识库无关或违规问题,将搜索不到任务数据

    go run ./ search --msg "苹果不洗能吃吗"
    rearch term violation or exceeding category
    

    kabi golang 实现 ai 知识库导入原理

    导入

    1. 接入 qdrant 和 openai cleint
    2. 解释原始知识库数据 为 q(问) a(答)
    3. 将 问题 经过 openai embedding 得到向量+答案存入 qdrant

    以下是 kbai go 导入逻辑代码

                qdrantclient := qdrant.newqdrantclient(configflags.qdrant, configflags.collection, configflags.vectorsize)
    			defer qdrantclient.close()
    			aiclient, err := ai.newaiclient(configflags.proxy, configflags.apikey)
    			if err != nil {
    				return err
    			}
    			if err = qdrantclient.createcollection(configflags.collection, configflags.vectorsize); err != nil {
    				return err
    			}
    			qas, err := converttoqas(datafile)
    			if err != nil {
    				return err
    			}
    			points := []*pb.pointstruct{}
    			logger.infow("import", "data", qas)
    			qpslenth := len(qas)
    			for i, qa := range qas {
    				embedding, err := aiclient.simplegetvec(qa.questions)
    				if err != nil {
    					logger.errorw("simplegetvec", "err", err, "question", qa.questions, "index", i, "total", qpslenth)
    					return err
    				}
    				point := buildpoint(qa.questions, qa.answers, embedding)
    				points = append(points, point)
    			}
    

    搜索

    1. 问题搜索,通过 openai embedding 得到向量
    2. 根据向量 从 qdrant 中搜索相似度大于 0.8 的数据
    3. 根据 qdrant 里的知识库答案(参考答案) + 从 chatgpt 提问 得到扩展知识
    4 条回复    2023-09-22 10:18:57 +08:00
    xyy003
        1
    xyy003  
       2023-09-22 08:24:22 +08:00
    解释原始知识库数据 为 q(问) a(答) 这一步是怎么转变的
    websong188
        2
    websong188  
    OP
       2023-09-22 09:29:02 +08:00
    @xyy003 这个应该是原始数据。大概是 golang 将原始数据文件 转换为 qa 数组,再将 qa 中的 q 通过 openai 获取到 embeddin,和 a 一起存入 qdrant 知识库
    xyy003
        3
    xyy003  
       2023-09-22 09:40:51 +08:00
    @websong188 那如何确保转换的 qa 数组的有效性呢 有相关的 prompt 吗
    websong188
        4
    websong188  
    OP
       2023-09-22 10:18:57 +08:00
    @xyy003 真实的知识库原始数据 需要自己提供,搜索的 prompt 规则是 用户问题+知识库的答案(参考答案) 的组合,得到偏向于 已有知识库设定的主题 扩展知识回答,当搜索的问题与 知识库的答案(参考答案) 相似度太低,就不给答案,防止问违规,知识库以外的问题
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2883 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 12:40 · PVG 20:40 · LAX 04:40 · JFK 07:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.