Metadata-Version: 2.1
Name: readet
Version: 0.1.0
Summary: LLM based tools and agents to fascilitate scientific research
Author-email: Hamed Haddadi <haddadi.h81@gmail.com>
License: Copyright (c) 2018 The Python Packaging Authority
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
Project-URL: Homepage, https://github.com/HamedHaddadi/readet
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE.md
Requires-Dist: accelerate==1.2.0
Requires-Dist: aiohappyeyeballs==2.4.4
Requires-Dist: aiohttp==3.11.10
Requires-Dist: aiosignal==1.3.1
Requires-Dist: annotated-types==0.7.0
Requires-Dist: anthropic==0.40.0
Requires-Dist: anyio==4.7.0
Requires-Dist: appnope==0.1.4
Requires-Dist: argon2-cffi==23.1.0
Requires-Dist: argon2-cffi-bindings==21.2.0
Requires-Dist: arrow==1.3.0
Requires-Dist: arxiv==2.1.3
Requires-Dist: asgiref==3.8.1
Requires-Dist: asttokens==3.0.0
Requires-Dist: async-lru==2.0.4
Requires-Dist: async-timeout==4.0.3
Requires-Dist: attrs==24.2.0
Requires-Dist: babel==2.16.0
Requires-Dist: backoff==2.2.1
Requires-Dist: bcrypt==4.2.1
Requires-Dist: beautifulsoup4==4.12.3
Requires-Dist: bleach==6.2.0
Requires-Dist: blinker==1.9.0
Requires-Dist: Bottleneck==1.4.2
Requires-Dist: Brotli==1.1.0
Requires-Dist: build==1.2.2.post1
Requires-Dist: cachetools==5.5.0
Requires-Dist: certifi==2024.8.30
Requires-Dist: cffi==1.17.1
Requires-Dist: charset-normalizer==3.4.0
Requires-Dist: chroma-hnswlib==0.7.6
Requires-Dist: chromadb==0.5.23
Requires-Dist: click==8.1.7
Requires-Dist: colorama==0.4.6
Requires-Dist: coloredlogs==15.0.1
Requires-Dist: comm==0.2.2
Requires-Dist: contourpy==1.3.1
Requires-Dist: cryptography==44.0.0
Requires-Dist: cycler==0.12.1
Requires-Dist: dataclasses-json==0.6.7
Requires-Dist: datasets==3.2.0
Requires-Dist: debugpy==1.8.10
Requires-Dist: decorator==5.1.1
Requires-Dist: defusedxml==0.7.1
Requires-Dist: Deprecated==1.2.15
Requires-Dist: dill==0.3.8
Requires-Dist: distro==1.9.0
Requires-Dist: durationpy==0.9
Requires-Dist: exceptiongroup==1.2.2
Requires-Dist: executing==2.1.0
Requires-Dist: faiss-cpu==1.9.0.post1
Requires-Dist: fastapi==0.115.6
Requires-Dist: fastjsonschema==2.21.1
Requires-Dist: feedparser==6.0.11
Requires-Dist: filelock==3.16.1
Requires-Dist: flatbuffers==24.3.25
Requires-Dist: fonttools==4.55.3
Requires-Dist: fqdn==1.5.1
Requires-Dist: frozenlist==1.5.0
Requires-Dist: fsspec==2024.9.0
Requires-Dist: gmpy2==2.2.1
Requires-Dist: google-auth==2.36.0
Requires-Dist: googleapis-common-protos==1.66.0
Requires-Dist: greenlet==3.1.1
Requires-Dist: grpcio==1.68.1
Requires-Dist: h11==0.14.0
Requires-Dist: httpcore==1.0.7
Requires-Dist: httptools==0.6.4
Requires-Dist: httpx==0.28.1
Requires-Dist: httpx-sse==0.4.0
Requires-Dist: huggingface-hub==0.26.5
Requires-Dist: humanfriendly==10.0
Requires-Dist: idna==3.10
Requires-Dist: importlib_metadata==8.5.0
Requires-Dist: importlib_resources==6.4.5
Requires-Dist: ipykernel==6.29.5
Requires-Dist: ipython==8.30.0
Requires-Dist: ipywidgets==8.1.5
Requires-Dist: isoduration==20.11.0
Requires-Dist: jedi==0.19.2
Requires-Dist: Jinja2==3.1.4
Requires-Dist: jiter==0.8.2
Requires-Dist: joblib==1.4.2
Requires-Dist: json5==0.10.0
Requires-Dist: jsonpatch==1.33
Requires-Dist: jsonpointer==3.0.0
Requires-Dist: jsonschema==4.23.0
Requires-Dist: jsonschema-specifications==2024.10.1
Requires-Dist: jupyter==1.1.1
Requires-Dist: jupyter-console==6.6.3
Requires-Dist: jupyter-events==0.10.0
Requires-Dist: jupyter-lsp==2.2.5
Requires-Dist: jupyter_client==8.6.3
Requires-Dist: jupyter_core==5.7.2
Requires-Dist: jupyter_server==2.14.2
Requires-Dist: jupyter_server_terminals==0.5.3
Requires-Dist: jupyterlab==4.3.3
Requires-Dist: jupyterlab_pygments==0.3.0
Requires-Dist: jupyterlab_server==2.27.3
Requires-Dist: jupyterlab_widgets==3.0.13
Requires-Dist: kiwisolver==1.4.7
Requires-Dist: kubernetes==31.0.0
Requires-Dist: langchain==0.3.11
Requires-Dist: langchain-anthropic==0.3.0
Requires-Dist: langchain-chroma==0.1.4
Requires-Dist: langchain-community==0.3.11
Requires-Dist: langchain-core==0.3.24
Requires-Dist: langchain-experimental==0.3.3
Requires-Dist: langchain-huggingface==0.1.2
Requires-Dist: langchain-openai==0.2.12
Requires-Dist: langchain-text-splitters==0.3.2
Requires-Dist: langchainhub==0.1.21
Requires-Dist: langgraph==0.2.58
Requires-Dist: langgraph-checkpoint==2.0.8
Requires-Dist: langgraph-sdk==0.1.43
Requires-Dist: langsmith==0.2.2
Requires-Dist: markdown-it-py==3.0.0
Requires-Dist: MarkupSafe==3.0.2
Requires-Dist: marshmallow==3.23.1
Requires-Dist: matplotlib==3.9.3
Requires-Dist: matplotlib-inline==0.1.7
Requires-Dist: mdurl==0.1.2
Requires-Dist: mistune==3.0.2
Requires-Dist: mmh3==5.0.1
Requires-Dist: monotonic==1.6
Requires-Dist: mpl_point_clicker==0.4.1
Requires-Dist: mpmath==1.3.0
Requires-Dist: msgpack==1.1.0
Requires-Dist: multidict==6.1.0
Requires-Dist: multiprocess==0.70.16
Requires-Dist: mypy-extensions==1.0.0
Requires-Dist: nbclient==0.10.1
Requires-Dist: nbconvert==7.16.4
Requires-Dist: nbformat==5.10.4
Requires-Dist: neo4j==5.27.0
Requires-Dist: nest-asyncio==1.6.0
Requires-Dist: networkx==3.4.2
Requires-Dist: nltk==3.9.1
Requires-Dist: notebook==7.3.1
Requires-Dist: notebook_shim==0.2.4
Requires-Dist: numexpr==2.10.2
Requires-Dist: numpy==1.26.4
Requires-Dist: oauthlib==3.2.2
Requires-Dist: onnxruntime==1.20.1
Requires-Dist: openai==1.57.2
Requires-Dist: opencv-python==4.10.0.84
Requires-Dist: opentelemetry-api==1.28.2
Requires-Dist: opentelemetry-exporter-otlp-proto-common==1.28.2
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc==1.28.2
Requires-Dist: opentelemetry-instrumentation==0.49b2
Requires-Dist: opentelemetry-instrumentation-asgi==0.49b2
Requires-Dist: opentelemetry-instrumentation-fastapi==0.49b2
Requires-Dist: opentelemetry-proto==1.28.2
Requires-Dist: opentelemetry-sdk==1.28.2
Requires-Dist: opentelemetry-semantic-conventions==0.49b2
Requires-Dist: opentelemetry-util-http==0.49b2
Requires-Dist: orjson==3.10.12
Requires-Dist: overrides==7.7.0
Requires-Dist: packaging==24.2
Requires-Dist: pandas==2.2.3
Requires-Dist: pandocfilters==1.5.1
Requires-Dist: parso==0.8.4
Requires-Dist: pdfminer.six==20231228
Requires-Dist: pdfplumber==0.11.4
Requires-Dist: pexpect==4.9.0
Requires-Dist: pillow==11.0.0
Requires-Dist: pkgutil_resolve_name==1.3.10
Requires-Dist: platformdirs==4.3.6
Requires-Dist: plotly==5.24.1
Requires-Dist: ply==3.11
Requires-Dist: posthog==3.7.4
Requires-Dist: prometheus_client==0.21.1
Requires-Dist: prompt_toolkit==3.0.48
Requires-Dist: propcache==0.2.1
Requires-Dist: protobuf==5.29.1
Requires-Dist: psutil==6.1.0
Requires-Dist: ptyprocess==0.7.0
Requires-Dist: pulsar-client==3.5.0
Requires-Dist: pure_eval==0.2.3
Requires-Dist: pyarrow==18.1.0
Requires-Dist: pyasn1==0.6.1
Requires-Dist: pyasn1_modules==0.4.1
Requires-Dist: pyclipper==1.3.0.post6
Requires-Dist: pycparser==2.22
Requires-Dist: pydantic==2.10.3
Requires-Dist: pydantic-settings==2.6.1
Requires-Dist: pydantic_core==2.27.1
Requires-Dist: Pygments==2.18.0
Requires-Dist: PyJWT==2.10.1
Requires-Dist: PyMuPDF==1.25.0
Requires-Dist: PyMuPDFb==1.24.10
Requires-Dist: pyOpenSSL==24.3.0
Requires-Dist: pyparsing==3.2.0
Requires-Dist: pypdf==5.1.0
Requires-Dist: pypdfium2==4.30.0
Requires-Dist: PyPika==0.48.9
Requires-Dist: pyproject_hooks==1.2.0
Requires-Dist: PyQt5==5.15.11
Requires-Dist: PyQt5-Qt5==5.15.15
Requires-Dist: PyQt5_sip==12.16.0
Requires-Dist: PySocks==1.7.1
Requires-Dist: python-dateutil==2.9.0.post0
Requires-Dist: python-dotenv==1.0.1
Requires-Dist: python-json-logger==2.0.7
Requires-Dist: pytz==2024.2
Requires-Dist: PyYAML==6.0.2
Requires-Dist: pyzmq==26.2.0
Requires-Dist: qtconsole==5.6.1
Requires-Dist: QtPy==2.4.2
Requires-Dist: rake-nltk==1.0.6
Requires-Dist: rank-bm25==0.2.2
Requires-Dist: rapidocr-onnxruntime==1.4.2
Requires-Dist: referencing==0.35.1
Requires-Dist: regex==2024.11.6
Requires-Dist: requests==2.32.3
Requires-Dist: requests-oauthlib==2.0.0
Requires-Dist: requests-toolbelt==1.0.0
Requires-Dist: rfc3339-validator==0.1.4
Requires-Dist: rfc3986-validator==0.1.1
Requires-Dist: rich==13.9.4
Requires-Dist: rpds-py==0.22.3
Requires-Dist: rsa==4.9
Requires-Dist: safetensors==0.4.5
Requires-Dist: scikit-learn==1.6.0
Requires-Dist: scipy==1.14.1
Requires-Dist: semanticscholar==0.9.0
Requires-Dist: Send2Trash==1.8.3
Requires-Dist: sentence-transformers==3.3.1
Requires-Dist: sentencepiece==0.2.0
Requires-Dist: serpapi==0.1.5
Requires-Dist: sgmllib3k==1.0.0
Requires-Dist: shapely==2.0.6
Requires-Dist: shellingham==1.5.4
Requires-Dist: sip==6.9.0
Requires-Dist: six==1.17.0
Requires-Dist: sniffio==1.3.1
Requires-Dist: soupsieve==2.6
Requires-Dist: SQLAlchemy==2.0.36
Requires-Dist: stack-data==0.6.3
Requires-Dist: starlette==0.41.3
Requires-Dist: sympy==1.13.1
Requires-Dist: tavily-python==0.5.0
Requires-Dist: tenacity==9.0.0
Requires-Dist: terminado==0.18.1
Requires-Dist: text-generation==0.7.0
Requires-Dist: threadpoolctl==3.5.0
Requires-Dist: tiktoken==0.8.0
Requires-Dist: tinycss2==1.4.0
Requires-Dist: tokenizers==0.20.3
Requires-Dist: tomli==2.2.1
Requires-Dist: torch==2.5.1
Requires-Dist: torchvision==0.20.1
Requires-Dist: tornado==6.4.2
Requires-Dist: tqdm==4.67.1
Requires-Dist: traitlets==5.14.3
Requires-Dist: transformers==4.46.3
Requires-Dist: typer==0.15.1
Requires-Dist: types-python-dateutil==2.9.0.20241206
Requires-Dist: types-requests==2.32.0.20241016
Requires-Dist: types-urllib3==1.26.25.14
Requires-Dist: typing-inspect==0.9.0
Requires-Dist: typing_extensions==4.12.2
Requires-Dist: tzdata==2024.2
Requires-Dist: unicodedata2==15.1.0
Requires-Dist: uri-template==1.3.0
Requires-Dist: urllib3==2.2.3
Requires-Dist: uvicorn==0.32.1
Requires-Dist: uvloop==0.21.0
Requires-Dist: watchfiles==1.0.3
Requires-Dist: wcwidth==0.2.13
Requires-Dist: webcolors==24.11.1
Requires-Dist: webencodings==0.5.1
Requires-Dist: websocket-client==1.8.0
Requires-Dist: websockets==14.1
Requires-Dist: widgetsnbextension==4.0.13
Requires-Dist: wikipedia==1.4.0
Requires-Dist: wrapt==1.17.0
Requires-Dist: xxhash==3.5.0
Requires-Dist: yarl==1.18.3
Requires-Dist: zipp==3.21.0

# readet
🚧 _until I prepare a more comprehensive documentation, use this readme to work with the package_ </br>
⚠️ If you run this package on a Windows machine, make sure you define the paths to files accordingly. </br>
⚠️ this documentation explains how to use the functionalities using a minimal set of inputs and using default arguments. But you can control parameters if you want. I will add the details in the documentation soon.

readet is a package developed using _LangChain_ for perusing scientific and technical literature. But all tools are applicable to any context. </br>
Eventhough several functionalities are included in this package, such as multi-agent systems, these modules are used more frequently: </br>
➡️ summarizers that are used to summarize a text, mostly pdf files. </br>
➡️ RAGs or Retrieval Augmented Generation tools which can be used to ask questions about a document. </br>
➡️ prebuilt agents that are used to download papers and patents in bulk. </br>

here is the current directory tree of the package </br>
```console
readet
├── __init__.py
├── bots
│   ├── __init__.py
│   ├── agents.py
│   ├── chat_tools.py
│   ├── components.py
│   ├── multi_agents.py
│   └── prebuilt.py
├── core
│   ├── __init__.py
│   ├── chains.py
│   ├── knowledge_graphs.py
│   ├── rags.py
│   ├── retrievers.py
│   ├── summarizers.py
│   └── tools.py
└── utils
    ├── __init__.py
    ├── docs.py
    ├── io.py
    ├── models.py
    ├── save_load.py
    └── schemas.py
```
👉 __How to install__ </br>
I recommend setting up a virtual environment with python version 3.10 </br>
```console
conda create -n <name> python=3.10
```
</br>
Then you can activate the environment using </br>

```console
conda activate <name>
```
</br>
This will make sure the package dependencies remain inside the virtual environment. 
The package can be installed using 
```console
pip3 install readet
```
I also included the _requirements.txt_ file. </br>

👉 __How to use__ </br>
This package uses several _API_ s that need API keys. Fortunaletly, all of them are free for a while (or forever if you do not use them too often). Here is the list of APIs </br>
1️⃣ OpenAI </br>
2️⃣ Serp API </br>
3️⃣ Anthropic </br>
4️⃣ Tavily Search </br>
5️⃣ LangChain </br>
6️⃣ Hugging Face </br>
apply for 1️⃣ to 3️⃣ first. With these APIs you can use utilize most of the functionalities in this package. But it is good to obtain all APIs at some point. </br>
The easiest way is to define all API keys in a _keys.env_ file and load it in your environment. The keys.env file is structured as </br>
OPENAI_API_KEY ="<you key>" </br>
TAVILY_API_KEY="<your key>" </br>
SERP_API_KEY="<your key>" </br>
ANTHROPIC_API_KEY ="<your key>" </br> 


👉 __example use case 1__ </br>
📖 _summarizers_ </br>
I use the _PlainSummarizer_ as an example: </br>
First, import necessary functions and classes </br> 
```python
# use this function to load your API keys from keys.env file
from readet.utils.io import load_keys
load_keys('keys.env')
from readet.core.summarizers import PlainSummarizers
```
</br>
Now define parameters: </br>

```python
# you can define any model from openai. Include 'openai-' before the model name.
# example: 'openai-gpt-4o'
chat_model = 'openai-gpt-4o-mini'
# degree of improvisation given to the model; 0 is preferred
temperature = 0
# instantiate the summarizer
plain_summarizer = PlainSummarizer(chat_model = chat_model, temperature = temperature)
```
</br>
Now specify the path to your pdf file and run the summarizer: </br>

```python
# note that your path might be different. In Windows, MacOS or Linux. Choose the exact path
pdf_file = '../files/my_file.pdf'
response = plain_summarizer(pdf_file)
```
</br>
You can print the response to see the summary </br>
Also, You may run the callable as much as you want to many pdf files: </br>

```python
pdf_files = ['./my_papers/paper.pdf', './my_patents/patent.pdf']
responses = {}
for count,pdf in enumerate(pdf_files):
    responses[f'summary_{count}'] = plain_summarizer(pdf)
```
</br>
Note that ingesting pdf files may take some time. For a general scientific paper it may take about 12 seconds. Later when I explain RAGs, I will describe a method to store ingested pdf files to avoid spending too much time reading pdf files from scratch. </br>

👉 __example use case 2__ </br>
📑 _RAGS_ </br>

RAGS are used to ask questions about a document. Say you have a pdf file and you want to ask questions about the content without reading it. RAGS ingest the pdf file and store in a database (a vectorstore) and use LLMs to respond to your questions based on what they hold. All RAGs in this package can keep their database on your local computer. So you do not need to add pdf files from scratch all the time. </br>
readet contains several RAGs but working with all of them is the same. Here is a list </br>
1️⃣ _PlainRAG_: simple but useful RAG to ask questions about a pdf file </br>
2️⃣ _RAGWithCitations_: similar to plainRAG, but returns the reference as well (see an example below) </br>
3️⃣ _AgenticRAG_: RAG with extra checks to make sure the answer is relevant to the context of the document </br>
4️⃣ _SelfRAG_: RAG with introspection, to avoid hallucination </br>
5️⃣ _AdaptiveRAG_: RAG that screens the question based on the relevance to the document. If not relevant, it gives an answer by google search. For example, it does not allow you to answer question about salsa dancing from a fluid dynamics text </br>

I start with the _PlainRAG_ which is the simplest model: </br>
```python
from readet.utils.io import load_keys
load_keys('keys.env')
from readet.core.rags import PlainRAG
```
</br>
You can define a RAG from scratch, or initialize it from saved data. I start from the former case </br>

```python
pdf_file = './my_papers/fluidflow.pdf'
# define your RAG store path here
store_path = './myRAGS'
rag = PlainRAG(documents = pdf_file, store_path = store_path)
```
</br>
This will give you a function for asking questions: </br>

```python
rag("who are the authors of this work?")
rag("what is the relationship between fluid pressure and solid content?")
```
</br>
Let's start the RAG from the previously saved database (or "vector store"). This will allow you to add new pdf files, or keep asking question from the old files. </br>
here are parameters that you need to pass to the class: </br>

``` python
# this parameter can also be None, if you do not want to add any new pdf file
new_pdf_file = './my_papers/turbulence.pdf'
# directory path
store_path = './myRAGS'
# either use a version number, ex 0,1,.., or pass 'last'
load_version_number = 'last'
rag2 = PlainRAG(documents = new_pdf_file, store_path = store_path, load_version_number = load_version_number)
```
</br>
Now you can ask questions. </br>

```python
rag2("what is the relationship between inertia and viscosity?")
```
</br>

Let's use _RAGWithCitations_ as well: </br>

```python
from readet.utils.io import load_keys
load_keys('keys.env')
from readet.core.rags import RAGWithCitations
pdf_file = './files/HaddadiMorrisJFM2014.pdf'
store_path = './RAGStore'
rag = RAGWithCitations(pdf_file, store_path = store_path)
rag("what is the relationship between inertia and normal stress?")
```
</br>
And here is the answer: 

```console
'Inertia affects the normal stress in suspensions by influencing the distribution of particles and their interactions under shear flow. As inertia increases, it can lead to higher particle pressure and changes in the normal stress differences, particularly the first normal stress difference (N1), which becomes more negative with increasing inertia and volume fraction. This relationship highlights the complex interplay between inertia and stress in particle-laden fluids, where increased inertia amplifies the effects of excluded volume and alters the stress distribution within the suspension.',
 'Haddadi, H. & Morris, J. F. (2023). Microstructure and Rheology of Finite Inertia Suspensions. J. Fluid Mech.'
```
</br>

_I use one more example of the AdaptiveRAG and move on to the next example usage. All other RAGs mentioned above work the same_ </br>

```python
from readet.core.rags import AdaptiveRAG
from readet.utils.io import load_keys
load_keys('keys.env')

# can be None if you want to load from database
pdf_file = './files/fluidflow.pdf'
store_path = './RAGFluid'
# if you want to load from database, choose a verion number or 'last'; else None
load_version_number = None

rag = AdaptiveRAG(documents = None, store_path = store_path, load_version_number = 'last')
rag("what is relationship between Reynolds number and viscosity?")

```
</br>
And here is the answer: </br>

```console
The Reynolds number (Re) is a dimensionless quantity that characterizes the flow regime in fluid dynamics, influenced by factors such as velocity, characteristic length, and viscosity. Generally, as Re increases, the effects of inertia become more significant compared to viscous forces, which can lead to changes in flow behavior. However, the viscosity itself may not show significant changes with varying Re, as indicated in the context provided.

```

👉 __example use case 3__</br>
📚 _search and download several papers from Google Scholar and Arxiv_ </br>
This tool has been a real convenience for me and I hope it helps you as well. I explain how it works. But I included this tool as an agent in a _multi agent_ chat bot and I deploy that chatbot soon. You can use this tool, summary and RAGs to peruse a lot papers. </br>
⚠️To use the Download functionality , you need _OpenAI_ and _Serp API_ API keys. Use the links in the first part of this ReadMe document to obtain the API keys. </br>
⚠️ ⚠️ To use this agent, prompting is important. Make sure to mention _"search and download"_ if you want the agent to download the files for you. Otherwise, it will output a list of papers and their information and links to download the article. </br>

```console
from readet.utils.io import load_keys
load_keys('keys.env')
from readet.bots.prebuilt import Download
```
</br>
Now you can define the parameters. These parameters are a path to save the downloaded files and maximum number of papers to download. Note that if you connection to the download faces a publisher paywall, the pdf file is not downloaded. But you can use the list of papers that are found to identify those papers and ask some to download it for you. </br>

``` python
save_path = './pdfs'
max_results = 100
downloader = Download(save_path = save_path, max_results = max_results)

# NOTE: if you want to download the paper, explicitly mention the word 'download'
download("search and download all papers related to finite inertia suspension flow of ellipsoidal particles")
```
The downloaded files are stored in _save_path_. A '.txt' file containing information of the papers is also stored in the _save_path_ directory </br>
For example, the first record in this file is : </br>

```console
*******************
Title: Numerical study of filament suspensions at finite inertia
Authors: AA Banaei, ME Rosti, L Brandt
Citation Count: 36
PDF Link: https://www.cambridge.org/core/services/aop-cambridge-core/content/view/5FA754F237DC68A6721F7C055FA08CEC/S0022112019007948a.pdf/div-class-title-numerical-study-of-filament-suspensions-at-finite-inertia-div.pdf
```
for example, you can send this file to colleagues via email. </br>

I am continuosly adding more functionalities. Hope this package is useful for your scientific discovery 🤞





















