实现与PDF进行聊天!(利用 Pinata、OpenAI 和 Streamlit等技术)

news/2024/10/17 23:41:16/
aidu_pl">
webkit-tap-highlight-color: rgba(0, 0, 0, 0);">

pdfproject_0">最近在GitHub上发现一个有趣的项目,由用户@ Jagroop2001开发的【chat-with-pdf】这个project!

我为此项目写了一个介绍和readme,感兴趣的可以点击链接:
https://github.com/Hyone-soul/chat-with-pdf/

在本教程中,我们将构建一个简单的聊天界面,允许用户上传PDF文件,使用OpenAI的API检索其内容,并在类似聊天的界面中显示响应。我们还将使用@pinata上传和存储PDF文件。

我们即将构建的项目预览:

前提条件:

  • 基本的Python知识
  • Pinata API密钥(用于上传PDF)
  • OpenAI API密钥(用于生成响应)
  • 安装了Streamlit(用于构建用户界面)

第1步:项目设置

首先创建一个新的Python项目目录:

mkdir chat-with-pdf
cd chat-with-pdf
python3 -m venv venv
source venv/bin/activate
pip install streamlit openai requests PyPDF2

接着,在项目的根目录创建一个.env文件,并添加以下环境变量:

PINATA_API_KEY=<你的Pinata API密钥>
PINATA_SECRET_API_KEY=<你的Pinata密钥>
OPENAI_API_KEY=<你的OpenAI API密钥>

你需要自己管理OPENAI_API_KEY,因为它是付费的。接下来,我们将讲解如何在Pinata中创建API密钥。

皮纳塔(Pinata)是什么?

Pinata是一个为IPFS(星际文件系统)提供文件存储和管理的平台,是一种去中心化的分布式文件存储系统。

  • 去中心化存储:Pinata帮助你在IPFS上存储文件,这是一个去中心化的网络。
  • 易于使用:它提供了用户友好的工具和API进行文件管理。
  • 文件可用性:Pinata通过将文件固定在IPFS上确保它们的可访问性。
  • NFT支持:非常适合存储NFT和Web3应用的元数据。
  • 经济实惠:相比传统云存储,Pinata可能是一种更具性价比的选择。

第2步:使用Pinata上传PDF

我们将使用Pinata的API来上传PDF文件,并获取每个文件的哈希值(CID)。创建一个名为pinata_helper.py的文件,用于处理PDF上传。

python">import os
import requests
from dotenv import load_dotenv# 加载环境变量
load_dotenv()# Pinata API URL,用于将文件固定到IPFS
PINATA_API_URL = "https://api.pinata.cloud/pinning/pinFileToIPFS"# 从环境变量中获取Pinata API密钥
PINATA_API_KEY = os.getenv("PINATA_API_KEY")
PINATA_SECRET_API_KEY = os.getenv("PINATA_SECRET_API_KEY")def upload_pdf_to_pinata(file_path):headers = {"pinata_api_key": PINATA_API_KEY,"pinata_secret_api_key": PINATA_SECRET_API_KEY}with open(file_path, 'rb') as file:response = requests.post(PINATA_API_URL, files={'file': file}, headers=headers)if response.status_code == 200:print("文件上传成功")return response.json()['IpfsHash']else:print(f"错误: {response.text}")return None

第3步:设置OpenAI

接下来,我们将创建一个函数,使用OpenAI的API与从PDF提取的文本进行交互。创建一个名为openai_helper.py的文件:

python">import os
from openai import OpenAI
from dotenv import load_dotenvload_dotenv()OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
client = OpenAI(api_key=OPENAI_API_KEY)def get_openai_response(text, pdf_text):try:messages = [{"role": "system", "content": "你是一名帮助回答PDF问题的助手。"},{"role": "user", "content": pdf_text},{"role": "user", "content": text}]response = client.chat.completions.create(model="gpt-4",messages=messages,max_tokens=100,temperature=0.7)return response.choices[0].message.contentexcept Exception as e:return f"错误: {str(e)}"

第4步:构建Streamlit界面

现在,我们已经准备好辅助函数,接下来构建一个Streamlit应用,用于上传PDF文件、从OpenAI获取响应并显示聊天。

创建一个名为app.py的文件:

python">import streamlit as st
import os
import time
from pinata_helper import upload_pdf_to_pinata
from openai_helper import get_openai_response
from PyPDF2 import PdfReader
from dotenv import load_dotenv# 加载环境变量
load_dotenv()st.set_page_config(page_title="与PDF聊天", layout="centered")st.title("使用OpenAI和Pinata与PDF聊天")uploaded_file = st.file_uploader("上传你的PDF文件", type="pdf")if "chat_history" not in st.session_state:st.session_state.chat_history = []
if "loading" not in st.session_state:st.session_state.loading = Falseif uploaded_file is not None:file_path = os.path.join("temp", uploaded_file.name)with open(file_path, "wb") as f:f.write(uploaded_file.getbuffer())st.write("正在将PDF上传到Pinata...")pdf_cid = upload_pdf_to_pinata(file_path)if pdf_cid:st.write(f"文件已上传到IPFS,CID为: {pdf_cid}")reader = PdfReader(file_path)pdf_text = ""for page in reader.pages:pdf_text += page.extract_text()if pdf_text:st.text_area("PDF内容", pdf_text, height=200)user_input = st.text_input("向PDF提问:", disabled=st.session_state.loading)if st.button("发送", disabled=st.session_state.loading):if user_input:st.session_state.loading = Truewith st.spinner("AI思考中..."):time.sleep(1)response = get_openai_response(user_input, pdf_text)st.session_state.chat_history.append({"user": user_input, "ai": response})st.session_state.input_text = ""st.session_state.loading = Falseif st.session_state.chat_history:for chat in st.session_state.chat_history:st.write(f"**你:** {chat['user']}")st.write(f"**AI:** {chat['ai']}")else:st.error("无法从PDF中提取文本。")else:st.error("PDF上传到Pinata失败。")

第5步:运行应用

使用以下命令在本地运行应用:

streamlit run app.py

第6步:代码解析

  • Pinata上传:用户上传PDF文件后,临时保存到本地,并通过upload_pdf_to_pinata函数上传到Pinata,Pinata返回一个表示文件在IPFS上的哈希值(CID)。
  • PDF提取:上传成功后,使用PyPDF2提取PDF内容并显示在文本区域。
  • OpenAI交互:用户可以通过输入框向PDF内容提问,get_openai_response函数将用户问题和PDF内容发送到OpenAI,并返回相关的响应。

http://www.ppmy.cn/news/1539841.html

相关文章

【人工智能AIGC术语100条】Shelly聊AI-重磅发布!

大家好&#xff0c;我是Shelly&#xff0c;一个专注于输出AI工具和科技前沿内容的AI应用教练&#xff0c;体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具&#xff0c;拥抱AI时代的到来。 01 人工智能&AIGC术语100条全网发布 在…

Linux SSH无密码使用私钥远程登录连接详细配置流程

文章目录 前言1. Linux 生成SSH秘钥对2. 修改SSH服务配置文件3. 客户端秘钥文件设置4. 本地SSH私钥连接测试5. Linux安装Cpolar工具6. 配置SSHTCP公网地址7. 远程SSH私钥连接测试8. 固定SSH公网地址9. 固定SSH地址测试 前言 本文将详细介绍如何将Linux SSH服务与cpolar相结合&…

React JSX 使用条件语句渲染UI的两种写法

只针对函数组件 1. 第一种写法&#xff1a; function App({ id }) {return id1? <h1>hello</h1> : <h1>world</h1>; } 或者&#xff1a; function App({ id }) {return (<h1>{id1 && "hello" || id2 && "wo…

C++的随机数操作

首先想到的肯定是rand()函数&#xff0c;但是这个有点问题 引入头文件<stdlib.h> 如果不引入种子&#xff0c;它的随机数不是随机数&#xff0c;是固定的一串数字 srand()函数&#xff0c;产生随机的种子 示例&#xff1a; 产生0-99的随机数 #include<stdlib.h&g…

Java工具类--OkHttp工具类

以springboot项目举例 1.pom添加maven依赖 <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>你的OkHttp版本</version> </dependency> 2.创建OkHttp工具类&#xff…

海思hi3536c配置内核支持USB摄像头

linux内核版本&#xff1a;linux-3.18.20 配置步骤 进入Device Drivers 选择Multimedia support&#xff0c;并进入 选择Media USB Adapters&#xff0c;并进入 如下图&#xff0c;选择这几项&#xff1a; 保存退出&#xff0c;重新编译内核下载 内核更新后&#xff0c…

Bug:通过反射修改@Autowired注入Bean的字段,明确存在,报错 NoSuchFieldException

【BUG】通过Autowired注入了一个Bean SeqNo&#xff0c;测试的时候需要修改其中的字段。通过传统的反射&#xff0c;无论如何都拿不到信息&#xff0c;关键是一方面可以通过IDEA跳转&#xff0c;一方面debug也确实能看到这个字段。但是每次调用set方法报错&#xff1a;NoSuchFi…

84 外网用户通过外网地址访问内网服务器

1. 组网需求 某公司内部对外提供Web、FTP和SMTP服务&#xff0c;而且提供两台Web服务器。公司内部网址为10.110.0.0/16。其中&#xff0c;内部FTP服务器地址为10.110.10.3/16&#xff0c;内部Web服务器1的IP地址为10.110.10.1/16&#xff0c;内部Web服务器2的IP地址为10.110.1…