Skip to content

Commit

Permalink
Merge branch 'main' into add-pdf-viewer
Browse files Browse the repository at this point in the history
  • Loading branch information
lfoppiano committed Dec 19, 2023
2 parents 5fd26bb + 3cd4af5 commit 21069a4
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 33 deletions.
33 changes: 33 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "Python 3",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
"customizations": {
"codespaces": {
"openFiles": [
"README.md",
"streamlit_app.py"
]
},
"vscode": {
"settings": {},
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance"
]
}
},
"updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y <packages.txt; [ -f requirements.txt ] && pip3 install --user -r requirements.txt; pip3 install --user streamlit; echo '✅ Packages installed and Requirements met'",
"postAttachCommand": {
"server": "streamlit run streamlit_app.py --server.enableCORS false --server.enableXsrfProtection false"
},
"portsAttributes": {
"8501": {
"label": "Application",
"onAutoForward": "openPreview"
}
},
"forwardPorts": [
8501
]
}
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@
.env.docker
**/**/.chroma
resources/db
build
build
dist
__pycache__
document_qa/__pycache__
document_qa_engine.egg-info/
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,32 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [0.3.4] - 2023-12-16

## Added

+ Add gpt4 and gpt4-turbo

## Changed

+ improved UI: replace combo boxes with dropdown box

## [0.3.3] - 2023-12-14

### Added

+ Add experimental PDF rendering in the page

### Fixed

+ Fix GrobidProcessors API implementation

## [0.3.2] - 2023-12-01

### Fixed

+ Remove memory when using Zephyr-7b-beta, that easily hallucinate

## [0.3.1] - 2023-11-22

### Added
Expand Down
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ license: apache-2.0

<img src="https://github.com/lfoppiano/document-qa/assets/15426/f0a04a86-96b3-406e-8303-904b93f00015" width=300 align="right" />

https://lfoppiano-document-qa.hf.space/

## Introduction

Question/Answering on scientific documents using LLMs: ChatGPT-3.5-turbo, Mistral-7b-instruct and Zephyr-7b-beta.
Question/Answering on scientific documents using LLMs: ChatGPT-3.5-turbo, GPT4, GPT4-Turbo, Mistral-7b-instruct and Zephyr-7b-beta.
The streamlit application demonstrates the implementation of a RAG (Retrieval Augmented Generation) on scientific documents, that we are developing at NIMS (National Institute for Materials Science), in Tsukuba, Japan.
Different to most of the projects, we focus on scientific articles.
We target only the full-text using [Grobid](https://github.com/kermitt2/grobid) which provides cleaner results than the raw PDF2Text converter (which is comparable with most of other solutions).
Expand All @@ -29,19 +31,14 @@ The conversation is kept in memory by a buffered sliding window memory (top 4 mo

(The image on the right was generated with https://huggingface.co/spaces/stabilityai/stable-diffusion)

**Demos**:
- (stable version): https://lfoppiano-document-qa.hf.space/
- (unstable version): https://document-insights.streamlit.app/



[<img src="https://img.youtube.com/vi/M4UaYs5WKGs/hqdefault.jpg" height="300" align="right"
/>](https://www.youtube.com/embed/M4UaYs5WKGs)

## Getting started

- Select the model+embedding combination you want to use
- If using OpenAI, enter your API Key ([Open AI](https://platform.openai.com/account/api-keys)~~ or [Huggingface](https://huggingface.co/docs/hub/security-tokens))~~.
- If using gpt3.5-turbo, gpt4 or gpt4-turbo, enter your API Key ([Open AI](https://platform.openai.com/account/api-keys)).
- Upload a scientific article as a PDF document. You will see a spinner or loading indicator while the processing is in progress.
- Once the spinner disappears, you can proceed to ask your questions

Expand All @@ -68,11 +65,22 @@ Indicates whether sending a question to the LLM (Language Model) or to the vecto
- Embeddings: the response will consist of the raw text from the document related to the question (based on the embeddings). This mode helps to test why sometimes the answers are not satisfying or incomplete.

### NER (Named Entities Recognition)

This feature is specifically crafted for people working with scientific documents in materials science.
It enables to run NER on the response from the LLM, to identify materials mentions and properties (quantities, measurements).
This feature leverages both [grobid-quantities](https://github.com/kermitt2/grobid-quanities) and [grobid-superconductors](https://github.com/lfoppiano/grobid-superconductors) external services.

### Troubleshooting
Error: `streamlit: Your system has an unsupported version of sqlite3. Chroma requires sqlite3 >= 3.35.0`.
Here the [solution on Linux](https://stackoverflow.com/questions/76958817/streamlit-your-system-has-an-unsupported-version-of-sqlite3-chroma-requires-sq).
For more information, see the [details](https://docs.trychroma.com/troubleshooting#sqlite) on Chroma website.

## Disclaimer on Data, Security, and Privacy ⚠️

Please read carefully:

- Avoid uploading sensitive data. We temporarily store text from the uploaded PDF documents only for processing your request, and we disclaim any responsibility for subsequent use or handling of the submitted data by third-party LLMs.
- Mistral and Zephyr are FREE to use and do not require any API, but as we leverage the free API entrypoint, there is no guarantee that all requests will go through. Use at your own risk.
- We do not assume responsibility for how the data is utilized by the LLM end-points API.

## Development notes

Expand Down
1 change: 1 addition & 0 deletions document_qa/document_qa_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from tqdm import tqdm



class DocumentQAEngine:
llm = None
qa_chain_type = None
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = ["setuptools", "setuptools-scm"]
build-backend = "setuptools.build_meta"

[tool.bumpversion]
current_version = "0.3.2"
current_version = "0.3.3"
commit = "true"
tag = "true"
tag_name = "v{new_version}"
Expand Down
12 changes: 6 additions & 6 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Grobid
grobid-quantities-client==0.4.0
grobid-client-python==0.0.5
grobid-client-python==0.0.7
grobid_tei_xml==0.1.3

# Utils
tqdm
pyyaml==6.0
pytest
tqdm==4.66.1
pyyaml==6.0.1
pytest==7.4.3
streamlit==1.29.0
lxml
Beautifulsoup4
Expand All @@ -15,10 +15,10 @@ watchdog
dateparser

# LLM
chromadb==0.4.15
chromadb==0.4.19
tiktoken==0.4.0
openai==0.27.7
langchain==0.0.314
langchain==0.0.350
typing-inspect==0.9.0
typing_extensions==4.8.0
pydantic==2.4.2
Expand Down
41 changes: 24 additions & 17 deletions streamlit_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
from document_qa.grobid_processors import GrobidAggregationProcessor, decorate_text_with_annotations
from grobid_client_generic import GrobidClientGeneric

OPENAI_MODELS = ['chatgpt-3.5-turbo',
"gpt-4",
"gpt-4-1106-preview"]

if 'rqa' not in st.session_state:
st.session_state['rqa'] = {}

Expand Down Expand Up @@ -123,17 +127,17 @@ def clear_memory():
# @st.cache_resource
def init_qa(model, api_key=None):
## For debug add: callbacks=[PromptLayerCallbackHandler(pl_tags=["langchain", "chatgpt", "document-qa"])])
if model == 'chatgpt-3.5-turbo':
if model in OPENAI_MODELS:
st.session_state['memory'] = ConversationBufferWindowMemory(k=4)
if api_key:
chat = ChatOpenAI(model_name="gpt-3.5-turbo",
chat = ChatOpenAI(model_name=model,
temperature=0,
openai_api_key=api_key,
frequency_penalty=0.1)
embeddings = OpenAIEmbeddings(openai_api_key=api_key)

else:
chat = ChatOpenAI(model_name="gpt-3.5-turbo",
chat = ChatOpenAI(model_name=model,
temperature=0,
frequency_penalty=0.1)
embeddings = OpenAIEmbeddings()
Expand Down Expand Up @@ -212,20 +216,23 @@ def play_old_messages():
# is_api_key_provided = st.session_state['api_key']

with st.sidebar:
st.session_state['model'] = model = st.radio(
"Model",
("chatgpt-3.5-turbo", "mistral-7b-instruct-v0.1", "zephyr-7b-beta"),
index=2,
captions=[
"ChatGPT 3.5 Turbo + Ada-002-text (embeddings)",
"Mistral-7B-Instruct-V0.1 + Sentence BERT (embeddings) :free:",
"Zephyr-7B-beta + Sentence BERT (embeddings) :free:"
st.session_state['model'] = model = st.selectbox(
"Model:",
options=[
"chatgpt-3.5-turbo",
"mistral-7b-instruct-v0.1",
"zephyr-7b-beta",
"gpt-4",
"gpt-4-1106-preview"
],
help="Select the LLM model and embeddings you want to use.",
disabled=st.session_state['doc_id'] is not None or st.session_state['uploaded'])
index=2,
placeholder="Select model",
help="Select the LLM model:",
disabled=st.session_state['doc_id'] is not None or st.session_state['uploaded']
)

st.markdown(
":warning: Mistral and Zephyr are **FREE** to use. Requests might fail anytime. Use at your own risk. :warning: ")
":warning: [Usage disclaimer](https://github.com/lfoppiano/document-qa/tree/review-interface#disclaimer-on-data-security-and-privacy-%EF%B8%8F) :warning: ")

if (model == 'mistral-7b-instruct-v0.1' or model == 'zephyr-7b-beta') and model not in st.session_state['api_keys']:
if 'HUGGINGFACEHUB_API_TOKEN' not in os.environ:
Expand All @@ -244,7 +251,7 @@ def play_old_messages():
# os.environ["HUGGINGFACEHUB_API_TOKEN"] = api_key
st.session_state['rqa'][model] = init_qa(model)

elif model == 'chatgpt-3.5-turbo' and model not in st.session_state['api_keys']:
elif model in OPENAI_MODELS and model not in st.session_state['api_keys']:
if 'OPENAI_API_KEY' not in os.environ:
api_key = st.text_input('OpenAI API Key', type="password")
st.markdown("Get it [here](https://platform.openai.com/account/api-keys)")
Expand Down Expand Up @@ -303,9 +310,9 @@ def play_old_messages():
help="Number of chunks to consider when answering a question",
disabled=not uploaded_file)

st.session_state['ner_processing'] = st.checkbox("Named Entities Recognition (NER) processing on LLM response")
st.session_state['ner_processing'] = st.checkbox("Identify materials and properties.")
st.markdown(
'**NER on LLM responses**: The responses from the LLMs are post-processed to extract <span style="color:orange">physical quantities, measurements</span> and <span style="color:green">materials</span> mentions.',
'The LLM responses undergo post-processing to extract <span style="color:orange">physical quantities, measurements</span>, and <span style="color:green">materials</span> mentions.',
unsafe_allow_html=True)

st.divider()
Expand Down

0 comments on commit 21069a4

Please sign in to comment.