AI智能体开发(三):实战构建研究助手Agent
项目概述
我们将构建一个学术研究助手Agent,它能够:
- 智能搜索- 根据主题搜索arXiv上的相关论文
- 自动阅读- 下载并解析PDF论文内容
- 提取关键信息- 识别研究方法、实验结果、结论
- 生成研究报告- 输出结构化的Markdown格式报告
- 保存结果- 将报告保存为文件,方便后续查阅
技术栈:
- 框架:LangChain
- LLM:GPT-4 API
- 向量库:Chroma(本地)
- 工具:arxiv、pypdf、markdown
环境准备
Step 1: 创建项目
# 创建项目目录mkdirresearch-agentcdresearch-agent# 创建虚拟环境python-mvenv venvsourcevenv/bin/activate# Linux/Mac# venv\Scripts\activate # WindowsStep 2: 安装依赖
创建requirements.txt:
langchain>=0.1.0 langchain-openai>=0.0.5 chromadb>=0.4.0 arxiv>=2.0.0 pypdf>=3.17.0 markdown>=3.5.0 python-dotenv>=1.0.0 tenacity>=8.2.0安装依赖:
pipinstall-rrequirements.txtStep 3: 配置环境变量
创建.env文件:
OPENAI_API_KEY=sk-your-api-key-here创建config.py:
importosfromdotenvimportload_dotenv load_dotenv()classConfig:OPENAI_API_KEY=os.getenv("OPENAI_API_KEY")# LLM配置LLM_MODEL="gpt-4"LLM_TEMPERATURE=0.7LLM_MAX_TOKENS=4000# 搜索配置MAX_SEARCH_RESULTS=5MAX_PAPER_LENGTH=3000# 每篇论文最大读取字符数# 输出配置OUTPUT_DIR="./reports"config=Config()# 确保输出目录存在os.makedirs(config.OUTPUT_DIR,exist_ok=True)核心组件实现
论文搜索工具
创建tools/paper_search.py:
importarxivfromtypingimportList,Dictfromconfigimportconfigdefsearch_papers(query:str,max_results:int=None)->List[Dict]:""" 搜索arXiv学术论文 Args: query: 搜索关键词 max_results: 最大返回结果数 Returns: 论文列表,每个论文包含标题、作者、摘要、链接等信息 """ifmax_resultsisNone:max_results=config.MAX_SEARCH_RESULTSprint(f"正在搜索论文:{query}")# 创建搜索对象search=arxiv.Search(query=query,max_results=max_results,sort_by=arxiv.SortCriterion.Relevance,sort_order=arxiv.SortOrder.Descending)papers=[]forresultinsearch.results():paper={'title':result.title,'authors':[author.nameforauthorinresult.authors],'summary':result.summary,'published':result.published.strftime('%Y-%m-%d'),'pdf_url':result.pdf_url,'entry_id':result.entry_id,'categories':result.categories}papers.append(paper)print(f"- 找到{len(papers)}篇相关论文")returnpapersdefformat_paper_info(paper:Dict)->str:"""格式化单篇论文信息"""authors_str=", ".join(paper['authors'][:3])# 只显示前3个作者iflen(paper['authors'])>3:authors_str+=" et al."returnf""" 标题:{paper['title']}作者:{authors_str}发表日期:{paper['published']}摘要:{paper['summary'][:500]}... 链接:{paper['entry_id']}分类:{', '.join(paper['categories'][:3])}""".strip()defformat_search_results(papers:List[Dict])->str:"""格式化搜索结果"""ifnotpapers:return"未找到相关论文"formatted=[]fori,paperinenumerate(papers,1):formatted.append(f"\n{'='*60}\n论文{i}:\n{format_paper_info(paper)}")return"\n".join(formatted)PDF阅读器
创建tools/pdf_reader.py:
importrequestsfrompypdfimportPdfReaderfromioimportBytesIOfromconfigimportconfigdefdownload_and_read_pdf(pdf_url:str,max_length:int=None)->str:""" 下载并读取PDF文件内容 Args: pdf_url: PDF文件的URL max_length: 最大读取字符数 Returns: PDF文本内容 """ifmax_lengthisNone:max_length=config.MAX_PAPER_LENGTHtry:print(f"正在下载PDF:{pdf_url[:80]}...")# 下载PDFresponse=requests.get(pdf_url,timeout=30)response.raise_for_status()# 读取PDF内容pdf_file=BytesIO(response.content)reader=PdfReader(pdf_file)# 提取文本text_parts=[]forpageinreader.pages:text=page.extract_text()iftext:text_parts.append(text)full_text="\n".join(text_parts)# 限制长度iflen(full_text)>max_length:full_text=full_text[:max_length]+"\n...(内容过长,已截断)"print(f"- 成功读取PDF,共{