基于【文心一言】的指定链接文档langchain问答

一、基于【文心一言千帆】的指定链接文档langchain问答

1.主要功能

基于给定的 URL ,回答问题。

2.环境构建

需要安装以下库

  • langchain
  • erniebot
  • faiss-cpu
  • gradio
  • beautifulsoup4

3.效果图

二、ERNIEBOT SDK简介

1.快速安装

执行如下命令,快速安装Python语言的最新版本ERNIE Bot SDK(推荐Python >= 3.8)。

css 复制代码
pip install --upgrade erniebot

2.快速使用

大家使用ERNIE Bot SDK之前,请首先申请并设置鉴权参数,具体请参考认证鉴权

** Python接口**

ini 复制代码
import erniebot

# List supported models
models = erniebot.Model.list()

print(models)
# ernie-bot             文心一言旗舰版
# ernie-bot-turbo       文心一言轻量版
# ernie-text-embedding  文心百中语义模型
# ernie-vilg-v2         文心一格模型

# Set authentication params
erniebot.api_type = "aistudio"
erniebot.access_token = "<access-token-for-aistudio>"

# Create a chat completion
response = erniebot.ChatCompletion.create(model="ernie-bot", messages=[{"role": "user", "content": "你好,请介绍下你自己"}])

print(response.result)

命令行接口(CLI)

ini 复制代码
# List supported models
erniebot api model.list

# Set authentication params for chat_completion.create
export EB_API_TYPE="aistudio"
export EB_ACCESS_TOKEN="<access-token-for-aistudio>"

# Create a chat completion (using ernie-bot, ernie-bot-turbo, etc.)
erniebot api chat_completion.create --model ernie-bot --message user "请介绍下你自己"

# Set authentication params for image.create
export EB_API_TYPE="yinian"
export EB_ACCESS_TOKEN="<access-token-for-yinian>"

# Generate images via ERNIE-ViLG
erniebot api image.create --model ernie-vilg-v2 --prompt "画一只驴肉火烧" --height 1024 --width 1024 --image-num 1

经典示例

对话补全(Chat Completion)

ERNIE Bot SDK提供具备对话补全能力的文心一言旗舰版模型ernie-bot和文心一言迅捷版模型ernie-bot-turbo。

旗舰版模型的效果更好,迅捷版模型的响应速度更快、推理时延更低,大家可以根据实际场景的需求选择合适的模型。

以下是调用文心一言旗舰版模型进行多轮对话的示例:

ini 复制代码
import erniebot

erniebot.api_type = "aistudio"
erniebot.access_token = "<access-token-for-aistudio>"

response = erniebot.ChatCompletion.create(
    model="ernie-bot",
    messages=[{
        "role": "user",
        "content": "请问你是谁?"
    }, {
        "role": "assistant",
        "content":
        "我是百度公司开发的人工智能语言模型,我的中文名是文心一言,英文名是ERNIE-Bot,可以协助您完成范围广泛的任务并提供有关各种主题的信息,比如回答问题,提供定义和解释及建议。如果您有任何问题,请随时向我提问。"
    }, {
        "role": "user",
        "content": "我在深圳,周末可以去哪里玩?"
    }])

print(response)

语义向量(Embedding)

ERNIE Bot SDK提供用于提取语义向量的Embedding模型。

该模型基于文心大模型,使用海量数据训练得到,为文心百中系统提供关键能力。该模型可以将字符串转为384维浮点数表达的语义向量,语义向量具备极其精准的语义表达能力,可以用于度量两个字符串之间的语义相似度。

大家可以使用以下代码提取句子的语义向量。

ini 复制代码
import erniebot

erniebot.api_type = "aistudio"
erniebot.access_token = "<access-token-for-aistudio>"

response = erniebot.Embedding.create(
    model="ernie-text-embedding",
    input=[
        "我是百度公司开发的人工智能语言模型,我的中文名是文心一言,英文名是ERNIE-Bot,可以协助您完成范围广泛的任务并提供有关各种主题的信息,比如回答问题,提供定义和解释及建议。如果您有任何问题,请随时向我提问。",
        "2018年深圳市各区GDP"
        ])

print(response)

大家可以登陆文心百中体验中心,体验更多大模型语义搜索的能力。

文生图(Image Generation)

ERNIE Bot SDK提供具备文生图能力的ERNIE-ViLG大模型。

该模型具备丰富的风格与强大的中文理解能力,支持生成多种尺寸的图片。

ini 复制代码
import erniebot

erniebot.api_type = "yinian"
erniebot.access_token = "<access-token-for-yinian>"

response = erniebot.Image.create(
    model="ernie-vilg-v2",
    prompt="雨后的桃花,8k,辛烷值渲染",
    width=512,
    height=512
)

print(response)

我们推荐两个撰写文生图Prompt提示词的文档,大家可以组合使用,创作出更加精美的图片。

大家也可登陆文心一格平台,体验更多AI艺术与创意辅助的能力。

函数调用(Function Calling)

ERNIE Bot SDK提供函数调用功能,即由大模型根据对话上下文确定何时以及如何调用函数。

借由函数调用,用户可以从大模型获取结构化数据,进而利用编程手段将大模型与已有的内外部API结合以构建应用。

以下是调用文心一言旗舰版模型进行函数调用的示例:

ini 复制代码
import erniebot

erniebot.api_type = "aistudio"
erniebot.access_token = "<access-token-for-aistudio>"

response = erniebot.ChatCompletion.create(
    model="ernie-bot",
    messages=[
        {
            "role": "user",
            "content": "深圳市今天气温如何?",
        }, ],
    functions=[{
        "name": "get_current_temperature",
        "description": "获取指定城市的气温",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {
                    "type": "string",
                    "description": "城市名称",
                },
                "unit": {
                    "type": "string",
                    "enum": ["摄氏度", "华氏度"],
                },
            },
            "required": ["location", "unit"],
        },
        "responses": {
            "type": "object",
            "properties": {
                "temperature": {
                    "type": "integer",
                    "description": "城市气温",
                },
                "unit": {
                    "type": "string",
                    "enum": ["摄氏度", "华氏度"],
                },
            },
        },
    }, ],
)
print(response)

三、gradio部署

1.安装所需包

python 复制代码
import os
os.system('pip install langchain')
os.system('pip install erniebot')
os.system('pip install faiss-cpu')
os.system('pip install gradio')
os.system('pip install beautifulsoup4')

import time
# 序列化和反序列化库
import pickle
# 文心一言库
import erniebot
# 进度条库
from tqdm import tqdm
# 文本加载器
from langchain.document_loaders import TextLoader
# 目录加载器
from langchain.document_loaders import DirectoryLoader
# Langchain默认使用的文本切割器,也是Langchain推荐使用的文本切割器
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 相似性搜索库
from langchain.vectorstores.faiss import FAISS
# 泛型库List
from typing import List
# 向量类
from langchain.schema.embeddings import Embeddings

from langchain.document_loaders import WebBaseLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
import textwrap
import langchain
import gradio as gr

2.界面设置

python 复制代码
# 1.说明
def create_ui_and_launch():
    web_dir = 'web'
    if not os.path.exists(web_dir):
        os.makedirs(web_dir)
    with gr.Blocks() as block:
        with gr.Row():
            gr.Markdown("""# <center> 基于【文心一言千帆】的指定链接文档langchain问答</center>""")
        with gr.Row():
            gr.HTML(
            """<img align="center" src='https://ai-studio-static-online.cdn.bcebos.com/15fde98025ab4e3ea373f12b209e6904aa88f1a45db440758f69734e763f3be9' width='100%'> <br>""")             
        with gr.Row():
            gr.Markdown("""# 需要安装:
                       - 1.langchain
                       - 2.erniebot sdk
                       - 3.详见 https://cloud.baidu.com/doc/WENXINWORKSHOP/s/wlmhm7vuo
                </center>
                """)
        create_components()
    block.queue(api_open=False, concurrency_count=8).launch()

3.输入设置

ini 复制代码
# 2.输入设置
def create_components():
    examples = [["https://zhuanlan.zhihu.com/p/85289282", "明朝的开国皇帝是谁"]]
    with gr.Row():
        with gr.Row():
            with gr.Column(scale=1):
                with gr.Accordion(label="基础配置", open=True):
                    with gr.Group():
                        access_key = gr.Textbox(
                            label="access-token-for-aistudio",
                            info="用于访问aistudio平台的AK",
                            type='password')
                        url = gr.Textbox(
                            label="链接",
                            info="文章链接")
            with gr.Column(scale=3):
                output_text = gr.Textbox(label="结   果", placeholder="结果...", lines=3)
                question = gr.Textbox(label="消息内容", placeholder="可以对文章进行提问")
    with gr.Row():
        send_text_btn = gr.Button("🚀发送消息🚀")
        regen_btn = gr.Button("✨一键清理✨")
    send_text_btn.click(fn=predict, inputs=[access_key,  url, question],
                        outputs=[output_text])
    regen_btn.click(fn=lambda value: gr.update(value=""), inputs=regen_btn, outputs=question)
    with gr.Row():
        gr_examples = gr.Examples(examples=examples, inputs=[url, question],
                                  label="输入示例 (点击选择例子)",
                                  examples_per_page=20)

4.生成库

python 复制代码
# 3.生成库
def generate_lib(url):
    # url="https://zhuanlan.zhihu.com/p/85289282"
    loader = WebBaseLoader(url)
    data = loader.load()
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=384, chunk_overlap=0,
                                                separators=["\n\n", "\n", " ", "", "。", ","])
    docs = text_splitter.split_documents(data)
    batch_size = 16
    # 块长度
    chunk_size = 384
    # 向量库
    embeddings = []
    texts = []
    metadatas = []
    # 分batch
    batch_docs = [docs[i:i + batch_size] for i in range(0, len(docs), batch_size)]

    for batch_doc in tqdm(batch_docs):
        try:
            response = erniebot.Embedding.create(
                model='ernie-text-embedding',
                input=[item.page_content for item in batch_doc]
            )
            embeddings += [item['embedding'] for item in response['data']]
            texts += [item.page_content for item in batch_doc]
            metadatas += [item.metadata for item in batch_doc]
            time.sleep(1)
        except:
            for text in tqdm(batch_doc):
                try:
                    response = erniebot.Embedding.create(
                        model='ernie-text-embedding',
                        input=[text.page_content]
                    )
                    embeddings.append(response['data'][0]['embedding'])
                    texts.append(text.page_content)
                    metadatas.append(text.metadata)
                    time.sleep(1)
                except:
                    continue
    # 组件向量库
    data = {
        "embeddings": embeddings,
        "texts": texts,
        'metadatas': metadatas,
    }
    # 保存向量库
    with open(os.path.join('web', 'data.pkl'), 'wb') as f:
        pickle.dump(data, f)

5.embedding定义

python 复制代码
# 4.embeddings
class ErniebotEmbeddings(Embeddings):
    def __init__(self, model: str = 'ernie-text-embedding',
                 batch_size: int = 16, embedding_size: int = 384):
        self.model = model
        self.batch_size = batch_size
        self.embedding_size = embedding_size

    def embed_documents(self, texts: List[str]) -> List[List[float]]:
        batch_texts = [texts[i: i + self.batch_size]
                       for i in range(0, len(texts), self.batch_size)]
        embeddings = []
        for batch_text in tqdm(batch_texts):
            try:
                response = erniebot.Embedding.create(
                    model=self.model,
                    input=batch_text
                )
                embeddings += [item['embedding'] for item in response['data']]
            except:
                for text in tqdm(batch_text):
                    try:
                        response = erniebot.Embedding.create(
                            model=self.model,
                            input=[text]
                        )
                        embeddings.append(response['data'][0]['embedding'])
                    except:
                        embeddings.append([0.0] * self.embedding_size)
                        continue
        return embeddings

    def embed_query(self, text: str) -> List[float]:
        response = erniebot.Embedding.create(
            model=self.model,
            input=[text]
        )
        return response['data'][0]['embedding']

6.保存知识库

python 复制代码
# 5.保存知识库
def save_knowledege():
    embedding = ErniebotEmbeddings()
    with open(os.path.join('web', 'data.pkl'), 'rb') as f:
        data = pickle.load(f)

    index = FAISS._FAISS__from(
        texts=data['texts'], embeddings=data['embeddings'], embedding=embedding, metadatas=data['metadatas']
    )
    # 保存知识库
    index.save_local('web')

7.预测并回答问题

python 复制代码
# 6.回答
def predict(ak, url, question):
    # 设置文心一言鉴权
    import erniebot
    erniebot.ak = ak
    erniebot.type = "aistudio"
    # 生成向量库
    generate_lib(url)
    # 保存知识库
    save_knowledege()

    embedding = ErniebotEmbeddings()
    # 加载知识库
    index = FAISS.load_local('web', embedding)
    prompt="请根据如下问题和文档给出回答。\n问题:%s\n参考:\n" % question
    k = 10
    search_type = 'similarity'  # mmr
    references = []
    for i, doc in enumerate(index.search(prompt, k=k, search_type=search_type)):
        prompt += '[%d] %s\n%s\n\n' % (i + 1, doc.metadata['source'], doc.page_content)
        reference = doc.metadata['source']
        if reference not in references:
            references.append(reference)

    prompt += '\n回答:\n'
    response = erniebot.ChatCompletion.create(
        model='ernie-bot-4',
        messages=[{
            'role': 'user',
            'content': prompt
        }],
        stream=True
    )
    answer=""
    for chunk in response:
        print(chunk['result'], end='')
        answer=answer+chunk['result']
    return answer

if __name__ == '__main__':
    create_ui_and_launch()
相关推荐
学习前端的小z20 分钟前
【AIGC】如何通过ChatGPT轻松制作个性化GPTs应用
人工智能·chatgpt·aigc
埃菲尔铁塔_CV算法1 小时前
人工智能图像算法:开启视觉新时代的钥匙
人工智能·算法
EasyCVR1 小时前
EHOME视频平台EasyCVR视频融合平台使用OBS进行RTMP推流,WebRTC播放出现抖动、卡顿如何解决?
人工智能·算法·ffmpeg·音视频·webrtc·监控视频接入
打羽毛球吗️1 小时前
机器学习中的两种主要思路:数据驱动与模型驱动
人工智能·机器学习
好喜欢吃红柚子1 小时前
万字长文解读空间、通道注意力机制机制和超详细代码逐行分析(SE,CBAM,SGE,CA,ECA,TA)
人工智能·pytorch·python·计算机视觉·cnn
小馒头学python1 小时前
机器学习是什么?AIGC又是什么?机器学习与AIGC未来科技的双引擎
人工智能·python·机器学习
神奇夜光杯1 小时前
Python酷库之旅-第三方库Pandas(202)
开发语言·人工智能·python·excel·pandas·标准库及第三方库·学习与成长
正义的彬彬侠1 小时前
《XGBoost算法的原理推导》12-14决策树复杂度的正则化项 公式解析
人工智能·决策树·机器学习·集成学习·boosting·xgboost
Debroon2 小时前
RuleAlign 规则对齐框架:将医生的诊断规则形式化并注入模型,无需额外人工标注的自动对齐方法
人工智能
羊小猪~~2 小时前
神经网络基础--什么是正向传播??什么是方向传播??
人工智能·pytorch·python·深度学习·神经网络·算法·机器学习