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

最近在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项目目录:

bash 复制代码
mkdir chat-with-pdf
cd chat-with-pdf
python3 -m venv venv
source venv/bin/activate
pip install streamlit openai requests PyPDF2

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

bash 复制代码
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_dotenv

load_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.content
    except 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 = False

if 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 = True

                    with 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 = False

            if 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步:运行应用

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

bash 复制代码
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,并返回相关的响应。
相关推荐
pen-ai1 分钟前
【优化方法】为什么梯度是最陡峭的方向?
人工智能·算法·机器学习·最小二乘法
刘广睿6 分钟前
给素材库加语音转写:Whisper 本地部署与批量字幕生成实践
人工智能·aigc·音视频·语音识别·效率工具
GitCode官方7 分钟前
玩转 AtomCode!AtomGit「码动四季・开源同行」夏季征稿获奖名单出炉!
人工智能·atomgit
艺杯羹9 分钟前
告别碎片化ToolCall:Model Context Protocol (MCP) 核心机理与私有数据总线落地实战
人工智能·microsoft·系统架构·大模型·mcp
cspttty10 分钟前
HR数字化校招准备路线:Excel、SQL、BI和AI工具怎么学
人工智能·sql·excel
知了一笑11 分钟前
产品先上线再开发
人工智能·互联网·aigc
m0_7345717611 分钟前
深入理解人工智能 chatGPT 核心协调与调度层 (Core Orchestration Layer)
人工智能·chatgpt
pt104313 分钟前
Cisco Splunk for AI Operations:AIOps机器学习
运维·网络·人工智能·机器学习
热爱编程的小李17 分钟前
安卫士设备数实时监测警报脚本
python
vortex519 分钟前
AI 提示词缓存命中机制解析
人工智能·缓存