import os from langchain.chat_models import ChatOpenAI from langchain.chains import RetrievalQA from langchain.memory import ConversationBufferMemory from langchain.prompts import PromptTemplate from langchain.agents import initialize_agent, AgentType from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.embeddings.huggingface import HuggingFaceEmbeddings from langchain.vectorstores import FAISS from langchain.tools import Tool from langchain.tools import DuckDuckGoSearchRun from langchain_core.documents import Document from dotenv import load_dotenv import os load_dotenv() apikey = os.getenv("MISTRAL_API_KEY") llm = ChatOpenAI( openai_api_key=apikey, openai_api_base="https://api.mistral.ai/v1", model="mistral-medium" ) prompt_template = PromptTemplate( input_variables=["user_prompt"], template="""You are a retriever agent tasked with creating an efficient search small query to retrieve academic papers from arxiv relevant to a user’s request. Based on the user’s input prompt, generate a concise and precise search query (a string of keywords or phrases) that will be used by the function `retrieve_and_extract_papers(query: str, max_papers: int = 3) -> str` to fetch up to 3 relevant papers. The query should focus on key concepts, avoid ambiguity, and prioritize relevance to ensure the extracted text is suitable for summarization. User Input Prompt: {user_prompt} Instructions: 1. Identify the core concepts, topics, or questions in the user prompt. 2. Formulate a search query using relevant keywords or short phrases. 3. Exclude overly broad or irrelevant terms to improve precision. 4. Output only the search query as a string. Example: - User Prompt: "Recent advancements in large language models for natural language processing" - Search Query: "large language models NLP advancements" Generate the search query for the provided user prompt. """ ) search_tool = DuckDuckGoSearchRun() tools = [ Tool( name="WebSearch", func=search_tool.run, description="Useful for fetching up-to-date healthcare information from the web.Use it rarely" ), ] retriever_agent = initialize_agent( tools=tools, agent_type=AgentType.CONVERSATIONAL_REACT_DESCRIPTION, llm=llm, verbose=True, prompt=prompt_template ) import arxiv import pdfplumber import requests import os from typing import List embedding_model = HuggingFaceEmbeddings(model_name="BAAI/bge-base-en-v1.5") def retrieve_and_extract_papers(query: str, max_papers: int = 3) -> str: """ Retrieves research papers from arXiv, downloads PDFs, extracts text, and returns a single string with papers separated by '---pprN: Title'. Args: query: Search query (e.g., "diffusion models 2024") max_papers: Number of papers to retrieve (default: 3) Returns: Single string with extracted text from PDFs, separated by '---pprN: Title' """ # Initialize arXiv client client = arxiv.Client() search = arxiv.Search( query=query, max_results=max_papers, sort_by=arxiv.SortCriterion.Relevance ) papers = list(client.results(search)) if not papers: return "No papers found for the query." # Create temporary directory for PDFs temp_dir = "temp_papers" os.makedirs(temp_dir, exist_ok=True) # Process each paper and collect extracted text formatted_texts = [] for i, paper in enumerate(papers, 1): try: # Download PDF pdf_url = paper.pdf_url response = requests.get(pdf_url) pdf_path = os.path.join(temp_dir, f"paper_{i}.pdf") with open(pdf_path, 'wb') as f: f.write(response.content) # Extract text from PDF text = "" with pdfplumber.open(pdf_path) as pdf: for page in pdf.pages: page_text = page.extract_text() if page_text: text += page_text + "\n" # Append formatted text with separator including paper title separator = f"---ppr{i}: {paper.title}" formatted_texts.append(f"{separator}\n{text}") # Clean up: Remove the downloaded PDF os.remove(pdf_path) except Exception as e: print(f"Error processing paper {i} ({paper.title}): {e}") formatted_texts.append(f"---ppr{i}: {paper.title}\nError: Could not process paper.") # Clean up: Remove temporary directory if empty if os.path.exists(temp_dir) and not os.listdir(temp_dir): os.rmdir(temp_dir) # Join all texts into a single string return "\n".join(formatted_texts) pdftext = retrieve_and_extract_papers(retriever_output) text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=50) document = Document(page_content=pdftext) documents = text_splitter.split_documents([document]) faiss_index = FAISS.from_documents(documents, embedding_model) faiss_index.save_local("faiss_index") retriever = faiss_index.as_retriever(search_kwargs={"k": 3})