✨ 核心特性
AI深度分析
DeepSeek R1模型,支持争议点提炼、机制解析、批判性分析等多维度总结
并发处理
多任务并发执行,API Key轮询使用,充分利用网络带宽
自动重试
智能重试机制,网络波动或API限流时自动恢复,确保任务完成
📋 前置准备
- 已安装Python 3.8+(推荐使用Miniconda)
- 已申请硅基流动API Key(用于调用DeepSeek R1)
- 已安装必要的Python包:pypdf, openai
Step 1: 安装依赖包
# 使用pip安装依赖
pip install pypdf openai
Step 2: 获取API Key
访问 硅基流动官网, 注册账号并获取API Key。建议准备多个Key以实现轮询并发。
- 准备3-5个API Key可以实现更高的并发稳定性
- DeepSeek R1思考时间较长,建议设置timeout≥300秒
- 硅基流动新用户通常有免费额度,足够日常使用
🔧 Automator工作流设置
创建快速操作
- 打开 Automator.app
- 选择 "快速操作" (Quick Action)
- 设置工作流:
- 工作流程收到当前:PDF文件
- 位于:访达.app (Finder)
- 传递输入:作为自变量
- 添加 "运行Shell脚本" 动作
- Shell选择:/bin/bash
- 传递输入:作为自变量
Shell脚本内容
复制以下代码到Automator的Shell脚本框中,记得修改第14行的Python路径:
# 1. 替换为你自己的Python路径
PYTHON_EXEC="/Users/你的用户名/miniconda3/bin/python"
# 2. 调用Python脚本
"$PYTHON_EXEC" - "$@" <<'EOF'
import sys
import os
import re
import time
import random
from pathlib import Path
from pypdf import PdfReader
from openai import OpenAI
# ================= 配置区域 =================
# ⚠️ 请替换为你自己的API Key
API_KEYS = [
"sk-your-api-key-1",
"sk-your-api-key-2",
"sk-your-api-key-3",
]
BASE_URL = "https://api.siliconflow.cn/v1"
MODEL_NAME = "deepseek-ai/DeepSeek-R1"
MAX_WORKERS = 4 # 并发数,建议不超过API Key数量
# --- 提示词配置 ---
PROMPT_1 = """
请作为一名资深的生物医学领域审稿人及科研专家读取文献。
严格按照下列框架总结文献:
✅关键词1✅关键词2✅关键词3✅关键词4……
🟫争议/切入点🟫:
🟪结论与机制解析🟪:
🟥数据来源与研究设计🟥:
⬛研究结果⬛:
🟧文章亮点🟧:
🟨文章局限性🟨:
📰双语摘要📰:
"""
PROMPT_2 = """帮我详细总结文章用到的数据,包括GWAS、临床数据等。"""
PROMPT_3 = """
从批判性角度分析文献,包括创新性、方法学、逻辑链条、数据解读等维度。
"""
TASK_LIST = [
("Task_01", PROMPT_1),
("Task_02", PROMPT_2),
("Task_03", PROMPT_3),
]
# ===========================================
def notify(title, message):
clean_msg = message.replace('"', '\\"')
os.system(f'osascript -e \'display notification "{clean_msg}" with title "{title}"\'')
def extract_text_from_pdf(pdf_path):
"""提取PDF文本(前50页)"""
try:
reader = PdfReader(pdf_path)
text = ""
for i, page in enumerate(reader.pages):
if i >= 50: # 读取前50页
break
page_text = page.extract_text()
if page_text:
text += page_text + "\n"
return text
except Exception as e:
return f"Error reading PDF: {str(e)}"
def call_ai_task(args):
"""调用AI,带重试机制"""
task_id, prompt, content, assigned_key = args
client = OpenAI(api_key=assigned_key, base_url=BASE_URL)
max_retries = 3 # 最多重试3次
for attempt in range(max_retries):
try:
response = client.chat.completions.create(
model=MODEL_NAME,
messages=[
{"role": "system", "content": "你是一个严谨的科研助手。必须强制使用中文回答。直接输出内容。"},
{"role": "user", "content": f"{prompt}\n\n论文内容:\n{content}"}
],
temperature=0.6,
timeout=300 # 5分钟超时
)
return task_id, response.choices[0].message.content
except Exception as e:
if attempt == max_retries - 1:
return task_id, f"Error: {str(e)}"
else:
wait_time = (attempt + 1) * 3 # 3s, 6s, 9s
time.sleep(wait_time)
def sanitize_filename(text):
"""清洗文件名"""
if not text: return "Untitled"
text = re.sub(r'[#*`]', '', text)
text = " ".join(text.split())
text = re.sub(r'[\\/*?:"<>|]', "_", text)
return text[:60].strip()
def main():
if len(sys.argv) < 2:
notify("错误", "未检测到输入文件")
return
pdf_path = Path(sys.argv[1])
notify("PDF AI分析", f"正在分析: {pdf_path.name}")
pdf_text = extract_text_from_pdf(str(pdf_path))
if "Error" in pdf_text:
notify("PDF读取失败", "文件可能已损坏")
return
# 准备任务
tasks = []
for i, (task_id, prompt_content) in enumerate(TASK_LIST):
assigned_key = API_KEYS[i % len(API_KEYS)]
tasks.append((task_id, prompt_content, pdf_text, assigned_key))
results = []
notify("AI思考中", f"正在执行{len(tasks)}个分析任务...")
# 并发执行
import concurrent.futures
with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
future_to_task = {executor.submit(call_ai_task, t): t[0] for t in tasks}
for future in concurrent.futures.as_completed(future_to_task):
try:
t_id, content = future.result()
results.append((t_id, content))
except Exception as e:
notify("任务失败", str(e))
# 保存结果
parent_dir = pdf_path.parent
for task_id, raw_content in results:
clean_content = re.sub(r'^```[a-zA-Z]*\n?', "", raw_content.strip())
clean_content = re.sub(r'\n?```$', "", clean_content.strip())
filename = sanitize_filename(clean_content) + ".md"
output_path = parent_dir / filename
with open(output_path, "w", encoding="utf-8") as f:
f.write(clean_content)
notify("分析完成", f"已生成{len(results)}个笔记文件")
if __name__ == "__main__":
main()
EOF
📖 使用方法
- 在Finder中找到需要分析的PDF文件
- 右键点击PDF文件,选择"快速操作" → "PDF AI分析"
- 等待系统通知提示"分析完成"
- 在PDF文件所在目录查看生成的Markdown笔记文件
- 可以同时选中多个PDF文件进行批量分析
- 生成的笔记文件会自动以论文关键词命名
- 分析过程中请保持网络连接稳定
🔧 常见问题
Q: Automator没有反应怎么办?
这通常是"静默失败"问题。请检查Python路径是否正确,依赖包是否已安装。
可以在终端手动运行脚本测试:which python3
Q: API调用超时怎么办?
DeepSeek R1思考时间较长,建议将timeout设置为300秒以上。 如果持续超时,可能是网络问题,可以尝试降低MAX_WORKERS并发数。
Q: 如何查看详细错误信息?
可以在脚本中添加日志输出功能,将错误信息写入桌面日志文件。 参考本教程的"Automator调试指南"部分。