【Langchain+Streamlit】打造一个旅游问答AI

news2024/11/15 21:55:08

        利用Langchain+Streamlit打造一个交互简单的旅游问答AI机器人,如果你有openai账号,可以按照如下的网址直接体验,如果你没有的话可以站内私信博主要一下临时key体验一下:

        产品使用传送门—— http://101.33.225.241:8501/

        这里有演示效果和代码讲解的视频传送门 ——【Langchain+Streamlit】超简单旅游问答AI(代码共享&账号分享)_哔哩哔哩_bilibili

        github传送门 —— GitHub - jerry1900/langchain_qabot: 用langchain,streamlit实现的简单问答机器人,只回答旅游方面的问题,适合langchain和streamlit初学者

        下面是一些使用效果截图,如果你问的是地理和旅游问题,他会给出很好的答案:

        如果你问的问题和旅游无关,他将不予回答:

         这么酷的旅游问答AI机器人,只用了不到100行代码,让我们来一起愉快地看代码吧!

1. 前端和页面部分用Streamlit构造,简单pyhon即可搞定

        首先引入必要的包,然后设置标题和主题内容(基本每行代码都有注释,结构简单清晰易懂):

import io

import streamlit as st
from PIL import Image

# 设置page_title内容
st.set_page_config(page_title="AI小万的旅游问答机器人")

# 设置首行内容
st.title('🤖AI小万的旅游问答机器人😜')

        然后设置左侧用于输入openai_key和base_url的sidebar:

# 设置左边的sidebar内容
with st.sidebar:
    # 设置输入openai_key和接口访问地址的两个输入框
    openai_key = st.text_input('OpenAI API Key', key='open_ai_key')
    openai_base_url = st.text_input('OpenAI BASE URL', 'https://api.openai.com', key='openai_base_url')

    # 设置一个可点击打开的展开区域
    with st.expander("🤓国内可访问的openai账号"):
        st.write("""
            1. 如果使用默认地址,可以使用openai官网账号(需科学上网🥵).
            2. 如果你没有openai官网账号,可以联系博主免费试用国内openai节点账号🥳.
        """)

        # 本地图片无法直接加载,需先将图片读取加载为bytes流,然后才能正常在streamlit中显示
        image_path = r"C:\Users\PycharmProjects\langchain\wechat.jpg"
        image = Image.open(image_path)
        image_bytes = io.BytesIO()
        image.save(image_bytes, format='JPEG')
        st.image(image_bytes, caption='AI小万老师的微信', use_column_width=True)

        在设置openai_key和openai_base_url的时候,使用了st的session技术,使用key来标记这两个元素,这两个元素在后面的代码中会使用到。

        我们在加载本地图片的时候有一点问题,没有办法直接用(如果是http网络资源直接加载就OK了,但是本地图片不行)。所以我们需要先把图片读取加载为bytes流,然后才能在streamlit中显示。

        至此,页面的主体结构就有了。

2.  构造一个输入用户问题以及openai相关参数,输出openai回答的函数

        首先是函数的入参说明和引入的包,主要是langchain相关的包,对于这一块不太熟的同学可以去看我以前的langchain专栏教学,这里是传送门——【2024最全最细Langchain教程-3 】Langchain模型I/O之提示Prompt(一)-CSDN博客:

def generate_response(input_text, open_ai_key, openai_base_url):
    """

    :param input_text:  用户输入的查询问题,类型为str
    :param open_ai_key: 用户输入的openai_key,类型为str
    :param openai_base_url: 用户输入的openai访问地址,类型为str
    :return: 返回langchain查询openai获得的结果,类型为str
    """

    from langchain_openai import ChatOpenAI
    from langchain.prompts import PromptTemplate
    from langchain_core.output_parsers import StrOutputParser

        构造一个语言模型包装器llm,注意这里的openai相关参数是调用函数的时候传入进来的:

  # 构造一个聊天模型包装器,key和url从函数输入中获取
    llm = ChatOpenAI(
        temperature=0,
        openai_api_key=open_ai_key,
        base_url=openai_base_url
    )

       构造完语言模型包装器之后,我们来构造提示词模板和提示词,这里的提示词模板是实现AI机器人只回答旅游相关问题的关键,这里你能领略到prompt engineering提示词工程的初步魅力:

# 构造一个模板template和一个prompt,从这里你可以看到提示词工程(prompt  engineering)的重要性
    template = """
    你是一个万贺创造的旅游问答机器人,你只回答用户关于旅游和地理方面的问题。
    你回答用户提问时使用的语言,要像诗一样优美,要能给用户画面感!
    如果用户的问题中没有出现地名或者没有出现如下词语则可以判定为与旅游无关:‘玩、旅游、好看、有趣、风景’
    
    案例:
    1. 用户问题:今天天气如何? 你的回答:抱歉,我只负责回答和旅游、地理相关的问题。
    2. 用户问题:你是谁?你的回答:我是万贺创造的旅游问答机器人,我只负责回答和旅游、地理相关的问题。
    3. 用户问题:今天股市表现如何?你的回答:抱歉我只负责回答和旅游、地理相关的问题
    
    以下是用户的问题:
    {question}
    """
    prompt = PromptTemplate(template=template, input_variables=["question"])

        构造完prompt之后我们开始构造输出解析器和链:

  # 构造一个输出解析器和链
    output_parser = StrOutputParser()
    chain = prompt | llm | output_parser

    response = chain.invoke({"question": input_text})
    st.info(response)

3. 构造一个用户用于输入问题的表单

        我们来构造一个给用户输入问题的表单,这里每一步都有详细的中文注释,细的不能再细了,大家自己看就好了:

# 构造一个用于输入问题的表单
with st.form('提交问题的表单'):
    text = st.text_area('请提一个您感兴趣的旅游或地理问题', '英国的首都在哪儿?')
    submitted = st.form_submit_button('提交')

    # 如果用户提交的key格式有误提醒用户
    if not st.session_state['open_ai_key'].startswith('sk-'):
        st.warning('您输入的openai秘钥格式有误')

    # 如果用户点击了提交按钮并且key格式无误则加载一个spinner加载状态
    if submitted and st.session_state['open_ai_key'].startswith('sk-'):
        with st.spinner("AI小万正在飞快加载中..."):
            # 加载状态进行中,调用我们之前构造的generate_response()方法,把用户的输入,key和url等参数传递给函数
            generate_response(text, st.session_state['open_ai_key'], st.session_state['openai_base_url'])
        st.success("AI小万为您加载完成!")

        至此,整个项目就构造完了,加上注释才不到100行。注意要运行这个代码,你要用python3.8以上的环境(建议使用虚拟环境,如何设置看我以前的视频)。这个项目主要需要streamlit,langchain,langchain_openai这些依赖库,可以自己pip下载。

        项目的运行也非常简单,用 streamlit run streamlit_app.py即可本地运行,运行之后在浏览器打开:http:\\localhost:8051 即可查看项目。你也可以在我提供的ur上看效果(http://101.33.225.241:8501/)。

        可以git上拉去代码实现,上面为了讲解把代码切成一块一块的了,下面是全部的代码方便大家下载:

import io

import streamlit as st
from PIL import Image

# 设置page_title内容
st.set_page_config(page_title="AI小万的旅游问答机器人")

# 设置首行内容
st.title('🤖AI小万的旅游问答机器人😜')

# 设置左边的sidebar内容
with st.sidebar:
    # 设置输入openai_key和接口访问地址的两个输入框
    openai_key = st.text_input('OpenAI API Key', key='open_ai_key')
    openai_base_url = st.text_input('OpenAI BASE URL', 'https://api.openai.com', key='openai_base_url')

    # 设置一个可点击打开的展开区域
    with st.expander("🤓国内可访问的openai账号"):
        st.write("""
            1. 如果使用默认地址,可以使用openai官网账号(需科学上网🥵).
            2. 如果你没有openai官网账号,可以联系博主免费试用国内openai节点账号🥳.
        """)

        # 本地图片无法直接加载,需先将图片读取加载为bytes流,然后才能正常在streamlit中显示
        image_path = r"C:\Users\PycharmProjects\langchain\wechat.jpg"
        image = Image.open(image_path)
        image_bytes = io.BytesIO()
        image.save(image_bytes, format='JPEG')
        st.image(image_bytes, caption='AI小万老师的微信', use_column_width=True)


def generate_response(input_text, open_ai_key, openai_base_url):
    """

    :param input_text:  用户输入的查询问题,类型为str
    :param open_ai_key: 用户输入的openai_key,类型为str
    :param openai_base_url: 用户输入的openai访问地址,类型为str
    :return: 返回langchain查询openai获得的结果,类型为str
    """

    from langchain_openai import ChatOpenAI

    from langchain.prompts import PromptTemplate
    from langchain_core.output_parsers import StrOutputParser

    # 构造一个聊天模型包装器,key和url从函数输入中获取
    llm = ChatOpenAI(
        temperature=0,
        openai_api_key=open_ai_key,
        base_url=openai_base_url
    )

    # 构造一个模板template和一个prompt,从这里你可以看到提示词工程(prompt  engineering)的重要性
    template = """
    你是一个万贺创造的旅游问答机器人,你只回答用户关于旅游和地理方面的问题。
    你回答用户提问时使用的语言,要像诗一样优美,要能给用户画面感!
    如果用户的问题中没有出现地名或者没有出现如下词语则可以判定为与旅游无关:‘玩、旅游、好看、有趣、风景’
    
    案例:
    1. 用户问题:今天天气如何? 你的回答:抱歉,我只负责回答和旅游、地理相关的问题。
    2. 用户问题:你是谁?你的回答:我是万贺创造的旅游问答机器人,我只负责回答和旅游、地理相关的问题。
    3. 用户问题:今天股市表现如何?你的回答:抱歉我只负责回答和旅游、地理相关的问题
    
    以下是用户的问题:
    {question}
    """
    prompt = PromptTemplate(template=template, input_variables=["question"])

    # 构造一个输出解析器和链
    output_parser = StrOutputParser()
    chain = prompt | llm | output_parser

    response = chain.invoke({"question": input_text})
    st.info(response)


# 构造一个用于输入问题的表单
with st.form('提交问题的表单'):
    text = st.text_area('请提一个您感兴趣的旅游或地理问题', '英国的首都在哪儿?')
    submitted = st.form_submit_button('提交')

    # 如果用户提交的key格式有误提醒用户
    if not st.session_state['open_ai_key'].startswith('sk-'):
        st.warning('您输入的openai秘钥格式有误')
    # 如果用户点击了提交按钮并且key格式无误则加载一个spinner加载状态
    if submitted and st.session_state['open_ai_key'].startswith('sk-'):
        with st.spinner("AI小万正在飞快加载中..."):
            # 加载状态进行中,调用我们之前构造的generate_response()方法,把用户的输入,key和url等参数传递给函数
            generate_response(text, st.session_state['open_ai_key'], st.session_state['openai_base_url'])
        st.success("AI小万为您加载完成!")

        以后我会尝试用国产的chatGLM来做一些内容,希望大家都能在AI领域玩的开心!

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

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

相关文章

[word] word小数点对齐怎么设置 #微信#其他#其他

word小数点对齐怎么设置 使用Word编辑文档的时候,如果有小技巧的话,可以解决很多遇到的问题,也让工作更高效的完成,下面给大家分享word小数点对齐怎么设置的小技巧。 1、设置格式 选中内容,点击段落一一制表符&#…

86 SRC挖掘-教育行业平台规则批量自动化

目录 涉及资源: 专属SRC范围小,所以难度大一些 CNVD挖到的漏洞要有一些影响面,才能拿到证书 教育漏洞平台给的面是很大的,给很多目标,我们按照常规思路来讲的话,自己去手工测试和提交这些漏洞&#xff0c…

webpack源码分析——truncateArgs函数

一、truncateArgs 函数 函数功能 该函数可以用于用户界面中的文本截断,确保长文本在有限的显示空间内能够适当显示,并且用户可以了解到部分文本已被省略。 函数参数 args:参数数组。用于输出到界面上maxLength:当前界面上可容纳…

Vue基础知识七

一 路由 1.1 生活里的路由与路由器 是为了实现多台设备上网 1.2 程序里的路由与路由器 是为了实现导航区与展示区来回切换; SPA单页面应用:就像前几章节里的项目,整个项目只有一个html文件; 案例 注意,最开始的时候…

嵌入式——串行外围设备接口(SPI)

目录 一、初识SPI 1. 介绍 2. 特性 补: 二、物理层 1. SS (Slave Select) 2. SCK (Serial Clock) 3. MOSI (Master Output, Slave Input) 4. MISO (Master Input&#xff0…

AI助力农作物自动采摘,基于YOLOv8全系列【n/s/m/l/x】参数模型开发构建作物番茄采摘场景下番茄成熟度检测识别分析系统

去年十一那会无意间刷到一个视频展示的就是德国机械收割机非常高效自动化地24小时不间断地在超广阔的土地上采摘各种作物,专家设计出来了很多用于采摘不同农作物的大型机械,看着非常震撼,但是我们国内农业的发展还是相对比较滞后的&#xff0…

Python机器学习库(numpy库)

文章目录 Python机器学习库(numpy库)1. 数据的维度2. numpy基础知识2.1 numpy概述2.1 numpy概述2.1 numpy概述2.2 numpy库的引用 3. ndarray数组的创建3.1 N维数组对象ndarray3.2 创建ndarray数组3.2.1 使用Python列表、元组创建ndarray数组3.2.2 使用nu…

C++ 动态规划 线性DP 数字三角形

给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。 73 8 8 1 02 7 4 4 4 5 2 6 5 输入格式 …

Quick BI中lod函数之lod_include

一、lod函数简介 LOD函数的全称是详细级别表达式(Level Of Detail Expressisons)。它主要是为了克服一些表达式之间计算颗粒度不一致的问题。比如,要计算第一季度各月销售收入占比,这里分子计算颗粒度为’月’,但是分…

栈的应用:括号匹配问题_有效的括号

假设表达式中允许包含两种括号:圆括号和方括号,嵌套顺序要求: 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的相同类型的左括号。 考虑下列括号序列: 分析如下: 计算机…

stable diffusion学习笔记——高清修复

ai画图中通常存在以下痛点: 受限于本地设备的性能(主要是显卡显存),无法跑出分辨率较高的图片。生图的时候分辨率一调大就爆显存。即便显存足够。目前主流的模型大多基于SD1.0和SD1.5,这些模型在训练的时候通常使用小…

机器学习-基础分类算法-KNN详解

KNN-k近邻算法 k-Nearest Neighbors 思想极度简单应用数学只是少效果好可以解释机器学习算法使用过程中的很多细节问题更完整的刻画机器学习应用的流程 创建简单测试用例 import numpy as np import matplotlib.pyplot as plt raw_data_X [[3.393533211, 2.331273381],[3.1…

单片机学习笔记---定时器和中断系统如何连起来工作

前面两节我们分别讲了中断系统和定时器,这节我们看看这两者连起来工作的原理。 说明:看这一节之前一定要先把前两节给看明白了再仔细琢磨这一节的每一张图! 前两节: 单片机学习笔记---中断系统(含外部中断&#xff…

Python基础知识:Python注释及print函数、input函数

在Python中,注释是对相应代码的解释,以增加代码的可读性,让用户能够更好地理解相应代码的含义。注释通过在相应代码后面加上“#”号来实现。比如以下代码 data.describe()#对数据集进行描述性分析 其中data.describe()为需要被执行的代码&a…

网络安全之漏洞扫描

漏洞是在硬件、软件、协议的具体实现或系统安全策略上存在的缺陷,从而可以使攻击者能够在未授权的情况下访问或破坏系统。这些缺陷、错误或不合理之处可能被有意或无意地利用,从而对一个组织的资产或运行造成不利影响,如信息系统被攻击或控制…

【高阶数据结构】红黑树

文章目录 前言什么是红黑树红黑树的性质红黑树结点的定义红黑树的插入情况一情况二情况三插入代码总结 验证是否为红黑树红黑树的删除 前言 前面我们学习了 AVL 树——高度平衡的二叉搜索树,AVL 树保证了结点的左右子树的高度差的绝对值不超过 1,也就是…

Nebula Siwi:基于图数据库的智能问答助手思路分析

本文重点分析 Nebula Siwi 智能问答思路,具体代码可参考[2],使用的数据集为 Basketballplayer[3]。部分数据和 schema 如下所示: 一.智能问答可实现的功能 1.Nebula Siwi 源码整体结构 主要包括前段(Vue)和后端&#…

Unity3d C# 在WebGL平台加载并解析xml文件实现总结

前言 xml是可扩展标记语言,由一系列的元素、属性、值节点等构成的一个树形结构,除了可读性差一点,别的用于存储一些结构化的数据还是比较方便的。这个功能在Unity3d端的实现是比较方便快捷的: void GetXML1() {string filePath …

【力扣hot100】刷题笔记Day3

前言 以撒真是一不小心就玩太久了,终于解锁骨哥嘞,抓紧来刷题,今天是easy双指针! 283. 移动零 - 力扣(LeetCode) 一个指针遍历,一个指针用于交换前面的0 class Solution(object):def moveZer…

简单说说mysql的日志

今天我们通过mysql日志了解mysqld的错误日志、慢查询日志、二进制日志,redolog, undolog等。揭示它们的作用和用途,让我们工作中更能驾驭mysql。 redo 日志 如果mysql事务提交后发生了宕机现象,那怎么保证数据的持久性与完整性?…