使用Python手寫一個智能PDF文檔助手
寫在前面
你是否想親手打造一個屬于自己的AI工具?是否想過用不到100行代碼就能實(shí)現(xiàn)一個智能聊天機(jī)器人
本文將帶你從零開始,手寫一個實(shí)用的AI小工具——智能PDF文檔助手!
通過這個項(xiàng)目,你將學(xué)會:
- 如何調(diào)用OpenAI API
- 如何處理PDF文檔
- 如何構(gòu)建一個完整的命令行工具
- 如何優(yōu)化代碼結(jié)構(gòu)和錯誤處理
項(xiàng)目簡介:智能PDF文檔助手
功能特性

項(xiàng)目亮點(diǎn)
| 功能 | 說明 |
|---|---|
| 多格式支持 | 支持PDF、TXT文件讀取 |
| AI驅(qū)動 | 使用GPT模型進(jìn)行智能分析 |
| 快速響應(yīng) | 流式輸出,實(shí)時查看結(jié)果 |
| 彩色輸出 | 命令行美化,體驗(yàn)更佳 |
| 進(jìn)度顯示 | 文件讀取進(jìn)度可視化 |
環(huán)境準(zhǔn)備
Python環(huán)境檢查
# 檢查Python版本
import sys
print(f"Python版本: {sys.version}")
# 推薦版本:Python 3.9 或更高
# 下載地址:https://www.python.org/downloads/
安裝依賴庫
創(chuàng)建 requirements.txt 文件:
openai>=1.0.0 pdfplumber>=0.10.0 python-dotenv>=1.0.0 colorama>=0.4.6 tqdm>=4.65.0
安裝命令:
# 創(chuàng)建虛擬環(huán)境(推薦) python -m venv ai_assistant_env # 激活虛擬環(huán)境 # Windows: ai_assistant_env\Scripts\activate # Mac/Linux: source ai_assistant_env/bin/activate # 安裝依賴 pip install -r requirements.txt
獲取OpenAI API Key
![]()
# 創(chuàng)建 .env 文件 echo OPENAI_API_KEY=your_api_key_here > .env echo OPENAI_BASE_URL=https://api.openai.com/v1 >> .env
項(xiàng)目結(jié)構(gòu)設(shè)計

核心代碼實(shí)現(xiàn)
配置文件 (config.py)
"""
配置文件 - 管理所有配置項(xiàng)
"""
import os
from dotenv import load_dotenv
# 加載環(huán)境變量
load_dotenv()
class Config:
"""應(yīng)用配置類"""
# OpenAI配置
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OPENAI_BASE_URL = os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1")
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-3.5-turbo")
# 應(yīng)用配置
MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB
CHUNK_SIZE = 1000 # 每次處理的字符數(shù)
MAX_TOKENS = 2000 # AI最大響應(yīng)長度
# 顏色配置
COLORS = {
"header": "\033[95m", # 紫色
"okblue": "\033[94m", # 藍(lán)色
"okgreen": "\033[92m", # 綠色
"warning": "\033[93m", # 黃色
"fail": "\033[91m", # 紅色
"endc": "\033[0m", # 結(jié)束
}
@classmethod
def color_print(cls, color_type, message):
"""彩色打印"""
color = cls.COLORS.get(color_type, "")
print(f"{color}{message}{cls.COLORS['endc']}")
# 驗(yàn)證配置
if not Config.OPENAI_API_KEY:
Config.color_print("fail", "? 請在.env文件中設(shè)置OPENAI_API_KEY")
exit(1)
PDF讀取模塊 (pdf_reader.py)
"""
PDF文檔讀取模塊
"""
import pdfplumber
from tqdm import tqdm
from config import Config
class PDFReader:
"""PDF文檔讀取器"""
def __init__(self, file_path):
self.file_path = file_path
self.content = ""
self.page_count = 0
def validate_file(self):
"""驗(yàn)證文件"""
if not self.file_path.endswith('.pdf'):
raise ValueError("? 僅支持PDF文件格式")
import os
file_size = os.path.getsize(self.file_path)
if file_size > Config.MAX_FILE_SIZE:
raise ValueError(f"? 文件過大,最大支持{Config.MAX_FILE_SIZE//1024//1024}MB")
def read_pdf(self):
"""讀取PDF內(nèi)容"""
try:
self.validate_file()
Config.color_print("okblue", f"?? 正在讀取文件: {self.file_path}")
with pdfplumber.open(self.file_path) as pdf:
self.page_count = len(pdf.pages)
Config.color_print("okgreen", f"?? 共 {self.page_count} 頁")
# 使用進(jìn)度條
for page in tqdm(pdf.pages, desc="讀取進(jìn)度", unit="頁"):
text = page.extract_text()
if text:
self.content += text + "\n\n"
Config.color_print("okgreen", f"? 讀取完成!共 {len(self.content)} 字符")
return self.content
except Exception as e:
Config.color_print("fail", f"? 讀取失敗: {str(e)}")
raise
def get_summary(self):
"""獲取文檔摘要(前500字)"""
return self.content[:500] + "..." if len(self.content) > 500 else self.content
AI客戶端模塊 (ai_client.py)
"""
OpenAI API客戶端模塊
"""
from openai import OpenAI
from config import Config
import time
class AIClient:
"""AI助手客戶端"""
def __init__(self):
self.client = OpenAI(
api_key=Config.OPENAI_API_KEY,
base_url=Config.OPENAI_BASE_URL
)
def ask(self, question, context=""):
"""向AI提問"""
try:
# 構(gòu)建消息
messages = [
{"role": "system", "content": "你是一個專業(yè)的文檔分析助手。"},
{"role": "user", "content": f"文檔內(nèi)容:\n{context}\n\n問題:{question}"}
]
Config.color_print("okblue", "?? AI正在思考...")
# 調(diào)用API
start_time = time.time()
response = self.client.chat.completions.create(
model=Config.OPENAI_MODEL,
messages=messages,
max_tokens=Config.MAX_TOKENS,
stream=True # 啟用流式輸出
)
# 流式輸出
answer = ""
Config.color_print("okgreen", "?? AI回答:")
for chunk in response:
if chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
answer += content
print(content, end="", flush=True)
print() # 換行
elapsed = time.time() - start_time
Config.color_print("okblue", f"?? 耗時: {elapsed:.2f}秒")
return answer
except Exception as e:
Config.color_print("fail", f"? API調(diào)用失敗: {str(e)}")
raise
def summarize(self, content):
"""生成文檔摘要"""
prompt = f"請為以下文檔生成一個簡潔的摘要(不超過200字):\n\n{content[:2000]}"
return self.ask(prompt, "")
def extract_keywords(self, content):
"""提取關(guān)鍵詞"""
prompt = f"請從以下文檔中提取5-10個關(guān)鍵詞:\n\n{content[:2000]}"
return self.ask(prompt, "")
主程序入口 (main.py)
"""
PDF智能助手主程序
"""
import argparse
import sys
from pdf_reader import PDFReader
from ai_client import AIClient
from config import Config
def print_banner():
"""打印歡迎界面"""
banner = """
╔═══════════════════════════════════════╗
║ ?? PDF智能文檔助手 v1.0 ?? ║
║ Powered by OpenAI GPT ║
╚═══════════════════════════════════════╝
"""
Config.color_print("header", banner)
def interactive_mode(reader, ai_client):
"""交互模式"""
Config.color_print("okgreen", "\n?? 進(jìn)入交互模式(輸入'quit'退出)")
context = reader.content[:3000] # 使用前3000字作為上下文
while True:
try:
question = input("\n?? 請輸入問題: ").strip()
if question.lower() in ['quit', 'exit', 'q']:
Config.color_print("warning", "?? 再見!")
break
if not question:
continue
ai_client.ask(question, context)
except KeyboardInterrupt:
Config.color_print("warning", "\n?? 用戶取消,再見!")
break
except Exception as e:
Config.color_print("fail", f"? 錯誤: {str(e)}")
def main():
"""主函數(shù)"""
parser = argparse.ArgumentParser(description="PDF智能文檔助手")
parser.add_argument("file", help="PDF文件路徑")
parser.add_argument("--summarize", action="store_true", help="生成文檔摘要")
parser.add_argument("--keywords", action="store_true", help="提取關(guān)鍵詞")
parser.add_argument("--ask", metavar="QUESTION", help="向AI提問")
args = parser.parse_args()
print_banner()
try:
# 讀取PDF
reader = PDFReader(args.file)
content = reader.read_pdf()
# 初始化AI客戶端
ai_client = AIClient()
# 執(zhí)行相應(yīng)功能
if args.summarize:
ai_client.summarize(content)
elif args.keywords:
ai_client.extract_keywords(content)
elif args.ask:
ai_client.ask(args.ask, content[:3000])
else:
# 進(jìn)入交互模式
interactive_mode(reader, ai_client)
except Exception as e:
Config.color_print("fail", f"\n? 程序異常: {str(e)}")
sys.exit(1)
if __name__ == "__main__":
main()
項(xiàng)目功能流程圖

使用示例
生成文檔摘要
python main.py document.pdf --summarize
提取關(guān)鍵詞
python main.py document.pdf --keywords
單次提問
python main.py document.pdf --ask "這篇文章的主要觀點(diǎn)是什么?"
交互模式
python main.py document.pdf
交互模式示例輸出:
?? 請輸入問題: 這篇文章講了什么? ?? AI正在思考... ?? AI回答: 這篇文章主要介紹了人工智能的發(fā)展歷程和應(yīng)用場景... ?? 耗時: 2.35秒 ?? 請輸入問題: 作者提到了哪些關(guān)鍵技術(shù)? ?? AI正在思考... ?? AI回答: 作者主要提到了以下幾項(xiàng)關(guān)鍵技術(shù): 1. 深度學(xué)習(xí) 2. 自然語言處理 3. 計算機(jī)視覺 ... ?? 耗時: 1.98秒 ?? 請輸入問題: quit ?? 再見!
AI小工具開發(fā)技能分布

進(jìn)階功能擴(kuò)展
添加批量處理功能
def batch_process(file_list, func):
"""批量處理多個文件"""
results = []
for file in tqdm(file_list, desc="批量處理"):
try:
reader = PDFReader(file)
content = reader.read_pdf()
result = func(content)
results.append({
"file": file,
"result": result,
"status": "success"
})
except Exception as e:
results.append({
"file": file,
"result": str(e),
"status": "failed"
})
return results
添加導(dǎo)出功能
def export_to_markdown(content, output_file):
"""導(dǎo)出為Markdown格式"""
with open(output_file, 'w', encoding='utf-8') as f:
f.write("# 文檔摘要\n\n")
f.write(content)
Config.color_print("okgreen", f"? 已導(dǎo)出到: {output_file}")
添加記憶功能
class ConversationMemory:
"""對話記憶管理"""
def __init__(self, max_history=5):
self.history = []
self.max_history = max_history
def add(self, question, answer):
"""添加對話記錄"""
self.history.append({
"question": question,
"answer": answer
})
# 保留最近N條記錄
if len(self.history) > self.max_history:
self.history = self.history[-self.max_history:]
def get_context(self):
"""獲取上下文"""
context = ""
for item in self.history:
context += f"Q: {item['question']}\nA: {item['answer']}\n\n"
return context
開發(fā)經(jīng)驗(yàn)總結(jié)
常見問題及解決方案
| 問題 | 解決方案 |
|---|---|
| API調(diào)用超時 | 添加重試機(jī)制,設(shè)置合理的timeout |
| 內(nèi)存占用過高 | 分塊處理大文件,使用生成器 |
| 用戶體驗(yàn)差 | 添加進(jìn)度條、彩色輸出、友好提示 |
| 代碼可維護(hù)性差 | 模塊化設(shè)計,添加類型注解和文檔 |
最佳實(shí)踐
# 1. 使用類型注解
def process_file(file_path: str) -> dict:
"""處理文件并返回結(jié)果字典"""
pass
# 2. 添加異常處理
try:
result = risky_operation()
except SpecificError as e:
logger.error(f"操作失敗: {e}")
# 執(zhí)行恢復(fù)操作
finally:
cleanup()
# 3. 使用日志記錄
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
# 4. 編寫單元測試
import unittest
class TestPDFReader(unittest.TestCase):
def test_validate_file(self):
reader = PDFReader("test.pdf")
# 測試代碼...
結(jié)語
恭喜你!
如果你已經(jīng)跟隨這篇文章完成了項(xiàng)目,那么你已經(jīng):
? 學(xué)會了如何調(diào)用OpenAI API
? 掌握了PDF文件處理技巧
? 了解了命令行工具的開發(fā)流程
? 獲得了一個實(shí)用的AI小工具
下一步建議:
- 嘗試添加新功能(如多格式支持、語音交互)
- 優(yōu)化用戶界面(如使用GUI框架)
- 部署到云端(如使用FastAPI構(gòu)建Web服務(wù))
- 開發(fā)更多AI小工具(如圖片識別、語音助手)
記?。鹤詈玫膶W(xué)習(xí)方式就是動手實(shí)踐!
以上就是使用Python手寫一個智能PDF文檔助手的詳細(xì)內(nèi)容,更多關(guān)于Python智能PDF文檔助手的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python logging設(shè)置和logger解析
這篇文章主要介紹了Python logging設(shè)置和logger解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-08-08
python中實(shí)現(xiàn)將多個print輸出合成一個數(shù)組
下面小編就為大家分享一篇python中實(shí)現(xiàn)將多個print輸出合成一個數(shù)組,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04
tensorflow獲取預(yù)訓(xùn)練模型某層參數(shù)并賦值到當(dāng)前網(wǎng)絡(luò)指定層方式
今天小編就為大家分享一篇tensorflow獲取預(yù)訓(xùn)練模型某層參數(shù)并賦值到當(dāng)前網(wǎng)絡(luò)指定層方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01
關(guān)于TensorFlow新舊版本函數(shù)接口變化詳解
今天小編就為大家分享一篇關(guān)于TensorFlow新舊版本函數(shù)接口變化詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02

