通过阿里云Milvus和通义千问快速构建基于专属知识库的问答系统

news2024/11/27 10:28:31

本文展示了如何使用阿里云向量检索Milvus和灵积(Dashscope)提供的通用千问大模型能力,快速构建一个基于专属知识库的问答系统。在示例中,我们通过接入灵积的通义千问API及文本嵌入(Embedding)API来实现LLM大模型的相关功能。

前提条件

  • 已创建Milvus实例。具体操作,请参见快速创建Milvus实例。

  • 已开通服务并获得API-KEY。具体操作,请参见开通DashScope并创建API-KEY。

使用限制

请确保您的运行环境中已安装Python 3.8或以上版本,以便顺利安装并使用DashScope。

操作流程

准备工作

  1. 安装相关的依赖库。

    pip3 install pymilvus tqdm dashscope
  2. 下载所需的知识库。

    本文示例使用了公开数据集CEC-Corpus。CEC-Corpus数据集包含332篇针对各类突发事件的新闻报道,语料和标注数据,这里我们只需要提取原始的新闻稿文本,并将其向量化后入库。

    git clone https://github.com/shijiebei2009/CEC-Corpus.git

步骤一:知识库向量化

  1. 创建embedding.py文件,内容如下所示。

    import os
    import time
    from tqdm import tqdm
    import dashscope
    from dashscope import TextEmbedding
    from pymilvus import connections, FieldSchema, CollectionSchema, DataType, Collection, utility
    
    
    def prepareData(path, batch_size=25):
        batch_docs = []
        for file in os.listdir(path):
            with open(path + '/' + file, 'r', encoding='utf-8') as f:
                batch_docs.append(f.read())
                if len(batch_docs) == batch_size:
                    yield batch_docs
                    batch_docs = []
    
        if batch_docs:
            yield batch_docs
    
    
    def getEmbedding(news):
        model = TextEmbedding.call(
            model=TextEmbedding.Models.text_embedding_v1,
            input=news
        )
        embeddings = [record['embedding'] for record in model.output['embeddings']]
        return embeddings if isinstance(news, list) else embeddings[0]
    
    
    if __name__ == '__main__':
    
        current_path = os.path.abspath(os.path.dirname(__file__))   # 当前目录
        root_path = os.path.abspath(os.path.join(current_path, '..'))   # 上级目录
        data_path = f'{root_path}/CEC-Corpus/raw corpus/allSourceText'  # 数据下载git clone https://github.com/shijiebei2009/CEC-Corpus.git
    
        # 配置Dashscope API KEY
        dashscope.api_key = '<YOUR_DASHSCOPE_API_KEY>'
    
        # 配置Milvus参数
        COLLECTION_NAME = 'CEC_Corpus'
        DIMENSION = 1536
        MILVUS_HOST = 'c-97a7d8038fb8****.milvus.aliyuncs.com'
        MILVUS_PORT = '19530'
        USER = 'root'
        PASSWORD = '<password>'
    
        connections.connect(host=MILVUS_HOST, port=MILVUS_PORT, user=USER, password=PASSWORD)
    
        # Remove collection if it already exists
        if utility.has_collection(COLLECTION_NAME):
            utility.drop_collection(COLLECTION_NAME)
    
        # Create collection which includes the id, title, and embedding.
        fields = [
            FieldSchema(name='id', dtype=DataType.INT64, descrition='Ids', is_primary=True, auto_id=False),
            FieldSchema(name='text', dtype=DataType.VARCHAR, description='Text', max_length=4096),
            FieldSchema(name='embedding', dtype=DataType.FLOAT_VECTOR, description='Embedding vectors', dim=DIMENSION)
        ]
        schema = CollectionSchema(fields=fields, description='CEC Corpus Collection')
        collection = Collection(name=COLLECTION_NAME, schema=schema)
    
        # Create an index for the collection.
        index_params = {
            'index_type': 'IVF_FLAT',
            'metric_type': 'L2',
            'params': {'nlist': 1024}
        }
        collection.create_index(field_name="embedding", index_params=index_params)
    
        id = 0
        for news in tqdm(list(prepareData(data_path))):
            ids = [id + i for i, _ in enumerate(news)]
            id += len(news)
    
            vectors = getEmbedding(news)
            # insert Milvus Collection
            for id, vector, doc in zip(ids, vectors, news):
                insert_doc = (doc[:498] + '..') if len(doc) > 500 else doc
                ins = [[id], [insert_doc], [vector]]  # Insert the title id, the text, and the text embedding vector
                collection.insert(ins)
                time.sleep(2)
    

    本文示例涉及以下参数,请您根据实际环境替换。

    参数

    说明

    data_path

    存放CEC-Corpus数据的路径。

    COLLECTION_NAME

    设置Miluvs Collection名称,您可以自定义。

    dashscope_api_key

    模型服务灵积的密钥。您可以在模型服务灵积控制台的API-KEY管理页面查看。

    DIMENSION

    向量维度。固定值为1536。

    MILVUS_HOST

    Milvus实例的公网地址。您可以在Milvus实例的实例详情页面查看。

    MILVUS_PORT

    Milvus实例的Proxy Port。您可以在Milvus实例的实例详情页面查看。默认为19530。

    USER

    配置为创建Milvus实例时,您自定义的用户。

    PASSWORD

    配置为创建Milvus实例时,您自定义用户的密码。

  2. 在Attu中您可以看到已经创建的Collection,具体操作请参见Attu工具管理。

    image

在本文示例中,我们将Embedding向量和新闻报道文稿一起存入Milvus中,同时构建索引类型采用了IVF_FLAT,在向量检索时,同时可以召回原始文稿。

步骤二:向量检索与知识问答

数据写入完成后,即可进行快速的向量检索。在通过提问搜索到相关的知识点后,我们可以按照特定的模板将“提问 + 知识点”作为prompt向LLM发起提问。在这里我们所使用的LLM是通义千问,这是阿里巴巴自主研发的超大规模语言模型,能够在用户自然语言输入的基础上,通过自然语言理解和语义分析,理解用户意图。通过提供尽可能清晰详细的指令(prompt),可以获得更符合预期的结果。这些能力都可以通过通义千问来获得。

本文示例设计的提问模板格式为:请基于我提供的内容回答问题。内容是{___},我的问题是{___},当然您也可以自行设计合适的模板。

创建answer.py文件,内容如下所示。

import os
import dashscope
from dashscope import Generation
from pymilvus import connections, FieldSchema, CollectionSchema, DataType, Collection
from dashscope import TextEmbedding


def getEmbedding(news):
    model = TextEmbedding.call(
        model=TextEmbedding.Models.text_embedding_v1,
        input=news
    )
    embeddings = [record['embedding'] for record in model.output['embeddings']]
    return embeddings if isinstance(news, list) else embeddings[0]

def getAnswer(query, context):
    prompt = f'''请基于```内的报道内容,回答我的问题。
	      ```
	      {context}
	      ```
	      我的问题是:{query}。
    '''

    rsp = Generation.call(model='qwen-turbo', prompt=prompt)
    return rsp.output.text


def search(text):
    # Search parameters for the index
    search_params = {
        "metric_type": "L2"
    }

    results = collection.search(
        data=[getEmbedding(text)],  # Embeded search value
        anns_field="embedding",  # Search across embeddings
        param=search_params,
        limit=1,  # Limit to five results per search
        output_fields=['text']  # Include title field in result
    )

    ret = []
    for hit in results[0]:
        ret.append(hit.entity.get('text'))
    return ret


if __name__ == '__main__':

    current_path = os.path.abspath(os.path.dirname(__file__))   # 当前目录
    root_path = os.path.abspath(os.path.join(current_path, '..'))   # 上级目录
    data_path = f'{root_path}/CEC-Corpus/raw corpus/allSourceText'

    # 配置Dashscope API KEY
    dashscope.api_key = '<YOUR_DASHSCOPE_API_KEY>'

    # 配置Milvus参数
    COLLECTION_NAME = 'CEC_Corpus'
    DIMENSION = 1536
    MILVUS_HOST = 'c-97a7d8038fb8****.milvus.aliyuncs.com'
    MILVUS_PORT = '19530'
    USER = 'root'
    PASSWORD = '<password>'

    connections.connect(host=MILVUS_HOST, port=MILVUS_PORT, user=USER, password=PASSWORD)

    fields = [
        FieldSchema(name='id', dtype=DataType.INT64, descrition='Ids', is_primary=True, auto_id=False),
        FieldSchema(name='text', dtype=DataType.VARCHAR, description='Text', max_length=4096),
        FieldSchema(name='embedding', dtype=DataType.FLOAT_VECTOR, description='Embedding vectors', dim=DIMENSION)
    ]
    schema = CollectionSchema(fields=fields, description='CEC Corpus Collection')
    collection = Collection(name=COLLECTION_NAME, schema=schema)

    # Load the collection into memory for searching
    collection.load()

    question = '北京中央电视台工地发生大火,发生在哪里?出动了多少辆消防车?人员伤亡情况如何?'
    context = search(question)
    answer = getAnswer(question, context)
    print(answer)

运行完成后,针对北京中央电视台工地发生大火,发生在哪里?出动了多少辆消防车?人员伤亡情况如何?的提问,会得到以下结果。

火灾发生在北京市朝阳区东三环中央电视台新址园区在建的附属文化中心大楼工地。出动了54辆消防车。目前尚无人员伤亡报告。

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

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

相关文章

中标麒麟操作系统:如何查看系统激活状态

中标麒麟操作系统&#xff1a;如何查看系统激活状态 1、图形界面查看方法方法一&#xff1a;任务栏查看方法二&#xff1a;通过“我的电脑”属性查看 2、命令行查看方法 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 本文将介绍两种查看系…

【AI 工具分享】

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

自动驾驶系列—厘米级精度:RTK技术如何革新自动驾驶定位

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

Python画图|多图共享X轴和Y轴

【1】引言 在python画图的众多场景中&#xff0c;存在多图对应X轴和Y轴可能一致的情形。 为此&#xff0c;尝试找到相关方法&#xff0c;不仅可以将代码写得更简洁&#xff0c;也更节省电脑内存&#xff0c;是提升工作效率的可选之路。 【2】官网教程 点击下方链接&#xf…

Python酷库之旅-第三方库Pandas(142)

目录 一、用法精讲 641、pandas.Timestamp.hour属性 641-1、语法 641-2、参数 641-3、功能 641-4、返回值 641-5、说明 641-6、用法 641-6-1、数据准备 641-6-2、代码示例 641-6-3、结果输出 642、pandas.Timestamp.is_leap_year属性 642-1、语法 642-2、参数 6…

Python爬虫(四)正则表达式(Regular Expressions for Python Crawlers)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

ctf.bugku-各种绕过呦

题目来源&#xff1a;各种绕过哟 - Bugku CTF 访问页面&#xff0c;得到代码如下&#xff1a; <?php highlight_file(flag.php); $_GET[id] urldecode($_GET[id]); $flag flag{xxxxxxxxxxxxxxxxxx}; if (isset($_GET[uname]) and isset($_POST[passwd])) {if ($_GET[una…

【STM32 HAL库】MPU6050姿态解算 卡尔曼滤波

【STM32 HAL库】MPU6050姿态解算 卡尔曼滤波 前言MPU6050寄存器代码详解mpu6050.cmpu6050.h 使用说明 前言 本篇文章基于卡尔曼滤波的原理详解与公式推导&#xff0c;来详细的解释下如何使用卡尔曼滤波来解算MPU6050的姿态 参考资料&#xff1a;Github_mpu6050 MPU6050寄存器…

利用网络流量分析仪进行网络故障排除:提升IT运维效率的关键工具

目录 一、什么是网络流量分析仪&#xff1f; 主要功能&#xff1a; 二、为什么网络流量分析仪在网络故障排除中如此重要&#xff1f; 三、实际案例&#xff1a;使用网络流量分析仪快速排查网络故障 案例一&#xff1a;流量拥塞导致的带宽不足 案例二&#xff1a;服务器响…

element-ui的树形结构样式调整,添加线条和边框样式

element-ui的树形结构样式调整&#xff0c;添加线条和边框样式 先看图效果&#xff1a; <template><div class"temperature_monitoring"><div class"temperature_monitoring_left"><div class"tree-container"><e…

萤石云 ezuikit-js 视频监控

父组件 <template><div class"securityProtectLargeScreen" v-if"waterWorks?.length > 0"><div class"leftSide"><ul class"leftItems flexColumnCenter"><liv-for"(item, index) in waterWork…

Java | Leetcode Java题解之第470题用Rand7()实现Rand10()

题目&#xff1a; 题解&#xff1a; class Solution extends SolBase {public int rand10() {int a, b, idx;while (true) {a rand7();b rand7();idx b (a - 1) * 7;if (idx < 40) {return 1 (idx - 1) % 10;}a idx - 40;b rand7();// get uniform dist from 1 - 63…

安卓13禁止用户打开开发者选项 android13禁止用户打开开发者选项

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改5.编译6.彩蛋1.前言 设置 =》关于平板电脑 =》版本号,一般的话,在这里连续点击就可以打开我们的开发者选项了。但是有些系统要进行保密,因此要禁止用户进入。 2.问题分析 这里我们是通过点…

FastAPI框架使用枚举来型来限定参数、FastApi框架隐藏没多大意义的Schemes模型部分内容以及常见的WSGI服务器Gunicorn、uWSGI了解

一、FastAPI框架使用枚举来型来限定参数 FastAPI框架验证时&#xff0c;有时需要通过枚举的方式来限定参数只能为某几个值中的一个&#xff0c;这时就可以使用FastAPI框架的枚举类型Enum了。publish:December 23, 2020 -Wednesday 代码如下&#xff1a; #引入Enum模块 from fa…

【自注意力与Transformer架构在自然语言处理中的演变与应用】

背景介绍 在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;序列到序列&#xff08;seq2seq&#xff09;模型和Transformer架构的出现&#xff0c;极大地推动了机器翻译、文本生成和其他语言任务的进展。传统的seq2seq模型通常依赖于循环神经网络&#xff08;RNN&…

【idea】切换多个仓库到一个分支

需求描述 打开个一个Project 里面包含多个子项目&#xff0c;每一个子项目都有一个自己的git仓库。在idea 中有没有一次性把多个项目切换到同一个分支上面。 解决方案 右键git -> branch 点击右上角的此轮 勾选Execute Branch Operations on All Roots 点击ommon Remote …

萱仔求职复习系列——2 Linux的常用方法(包含基础进阶高级操作)

由于最近接了一个笔试&#xff0c;发现笔试可能涉及到Linux&#xff0c;我准备临时抱佛脚一下赶紧复习一下Linux的用法哈哈。Linux 的基础用法包含文件系统操作、权限管理、网络配置、进程管理等基本命令&#xff1b;进阶操作包括网络调试、包管理、服务管理和用户管理等&#…

【jdk19虚拟线程 VS 普通线程】

文章目录 一.什么是虚拟线程二.虚拟线程与普通线程的区别1.普通线程2.虚拟线程3. 实际应用中的区别 三.上demo对比性能。1.线程池配置2.Service实现3.测试结果 四.小结 一.什么是虚拟线程 虚拟线程&#xff0c;也称作轻量级线程&#xff0c;是由JVM直接管理的线程类型&#xf…

jmeter入门:脚本录制

1.设置代理。 网络连接-》代理-》手动设置代理. ip&#xff1a; 127.0.0.1&#xff0c; port&#xff1a;8888 2. add thread group 3. add HTTP(s) test script recorder, target controller chooses Test plan-> thread Group 4. click start. then open the browser …

Golang | Leetcode Golang题解之第467题环绕字符串中唯一的子字符串

题目&#xff1a; 题解&#xff1a; func findSubstringInWraproundString(p string) (ans int) {dp : [26]int{}k : 0for i, ch : range p {if i > 0 && (byte(ch)-p[i-1]26)%26 1 { // 字符之差为 1 或 -25k} else {k 1}dp[ch-a] max(dp[ch-a], k)}for _, v :…