Skip to content
This repository was archived by the owner on Dec 11, 2025. It is now read-only.

Commit a0ca4b4

Browse files
committed
v4.0.0
1 parent 8afdd9c commit a0ca4b4

7 files changed

Lines changed: 172 additions & 12 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ Choose the task among:
7272
- *autotrain*: fine-tune a model on a specific downstream task with autotrain-advanced, just by specifying you HF username, HF writing token and the path to a yaml config file for the training
7373
- *spaces-api-supabase*: use HF Spaces API in combination with Supabase PostgreSQL databases in order to unleash more powerful LLMs and larger RAG-oriented vector databases - **MULTILINGUAL**
7474
- *llama.cpp-and-qdrant*: same as *retrieval-text-generation*, but uses **llama.cpp** as inference engine, so you MUST NOT specify a model - **MULTILINGUAL**
75+
- *build-your-llm*: Build a customizable chat LLM combining a Qdrant database with your PDFs and the power of Anthropic, OpenAI, Cohere or Groq models: you just need an API key! To build the Qdrant database, have to pass either a pdf/a bunch of pdfs specified as comma-separated paths or a directory where all the pdfs of interest are stored (**DO NOT** provide both); you can also specify the language in which the PDF is written, using [ISO nomenclature](https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes) - **MULTILINGUAL**
7576
- *image-retrieval-search*: search an image database uploading a folder as database input. The folder should have the following structure:
7677

7778
```

docker/Dockerfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ WORKDIR /app
77
# Add the current directory contents into the container at /app
88
ADD . /app
99

10+
RUN pip uninstall -y tokenizers
11+
12+
RUN pip install tokenizers==0.19.1
13+
1014
# Expose the port that the application will run on
1115
EXPOSE 8760
1216

docker/build_your_llm.py

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
from langchain_anthropic import ChatAnthropic
2+
from langchain_cohere import ChatCohere
3+
from langchain_groq import ChatGroq
4+
from langchain_openai import ChatOpenAI
5+
from langchain_core.runnables.history import RunnableWithMessageHistory
6+
from langchain_community.chat_message_histories import SQLChatMessageHistory
7+
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
8+
import gradio as gr
9+
from argparse import ArgumentParser
10+
from qdrant_client import QdrantClient
11+
from sentence_transformers import SentenceTransformer
12+
from utils import *
13+
import os
14+
import subprocess as sp
15+
16+
argparse = ArgumentParser()
17+
18+
argparse.add_argument(
19+
"-pf",
20+
"--pdf_file",
21+
help="Single pdf file or N pdfs reported like this: /path/to/file1.pdf,/path/to/file2.pdf,...,/path/to/fileN.pdf (there is no strict naming, you just need to provide them comma-separated)",
22+
required=False,
23+
default="No file"
24+
)
25+
26+
argparse.add_argument(
27+
"-d",
28+
"--directory",
29+
help="Directory where all your pdfs of interest are stored",
30+
required=False,
31+
default="No directory"
32+
)
33+
34+
argparse.add_argument(
35+
"-l",
36+
"--language",
37+
help="Language of the written content contained in the pdfs",
38+
required=False,
39+
default="Same as query"
40+
)
41+
42+
args = argparse.parse_args()
43+
44+
45+
pdff = args.pdf_file
46+
dirs = args.directory
47+
lan = args.language
48+
49+
50+
if pdff.replace("\\","").replace("'","") != "None" and dirs.replace("\\","").replace("'","") == "No directory":
51+
pdfs = pdff.replace("\\","/").replace("'","").split(",")
52+
else:
53+
pdfs = [os.path.join(dirs.replace("\\","/").replace("'",""), f) for f in os.listdir(dirs.replace("\\","/").replace("'","")) if f.endswith(".pdf")]
54+
55+
client = QdrantClient(host="host.docker.internal", port="6333")
56+
encoder = SentenceTransformer("all-MiniLM-L6-v2")
57+
58+
pdfdb = PDFdatabase(pdfs, encoder, client)
59+
pdfdb.preprocess()
60+
pdfdb.collect_data()
61+
pdfdb.qdrant_collection_and_upload()
62+
63+
sp.run("rm -rf memory.db", shell=True)
64+
65+
def get_session_history(session_id):
66+
return SQLChatMessageHistory(session_id, "sqlite:///memory.db")
67+
68+
NAME2CHAT = {"Cohere": ChatCohere, "claude-3-opus-20240229": ChatAnthropic, "claude-3-sonnet-20240229": ChatAnthropic, "claude-3-haiku-20240307": ChatAnthropic, "llama3-8b-8192": ChatGroq, "llama3-70b-8192": ChatGroq, "mixtral-8x7b-32768": ChatGroq, "gemma-7b-it": ChatGroq, "gpt-4o": ChatOpenAI, "gpt-3.5-turbo-0125": ChatOpenAI}
69+
NAME2APIKEY = {"Cohere": "COHERE_API_KEY", "claude-3-opus-20240229": "ANTHROPIC_API_KEY", "claude-3-sonnet-20240229": "ANTHROPIC_API_KEY", "claude-3-haiku-20240307": "ANTHROPIC_API_KEY", "llama3-8b-8192": "GROQ_API_KEY", "llama3-70b-8192": "GROQ_API_KEY", "mixtral-8x7b-32768": "GROQ_API_KEY", "gemma-7b-it": "GROQ_API_KEY", "gpt-4o": "OPENAI_API_KEY", "gpt-3.5-turbo-0125": "OPENAI_API_KEY"}
70+
71+
72+
73+
system_template = "You are an helpful assistant that can rely on this: {context} and on the previous message history as context, and from that you build a context and history-aware reply to this user input:"
74+
75+
76+
77+
def reply(message, history, name, api_key, temperature, max_new_tokens, sessionid):
78+
global pdfdb
79+
os.environ[NAME2APIKEY[name]] = api_key
80+
if name == "Cohere":
81+
model = NAME2CHAT[name](temperature=temperature, max_tokens=max_new_tokens)
82+
else:
83+
model = NAME2CHAT[name](model=name,temperature=temperature, max_tokens=max_new_tokens)
84+
prompt_template = ChatPromptTemplate.from_messages(
85+
[("system", system_template),
86+
MessagesPlaceholder(variable_name="history"),
87+
("human", "{input}")]
88+
)
89+
chain = prompt_template | model
90+
runnable_with_history = RunnableWithMessageHistory(
91+
chain,
92+
get_session_history,
93+
input_messages_key="input",
94+
history_messages_key="history",
95+
)
96+
txt = Translation(message, "en")
97+
if txt.original == "en" and lan.replace("\\","").replace("'","") == "None":
98+
txt2txt = NeuralSearcher(pdfdb.collection_name, pdfdb.client, pdfdb.encoder)
99+
results = txt2txt.search(message)
100+
response = runnable_with_history.invoke({"context": results[0]["text"], "input": message}, config={"configurable": {"session_id": sessionid}})##CONFIGURE!
101+
return response.content
102+
elif txt.original == "en" and lan.replace("\\","").replace("'","") != "None":
103+
txt2txt = NeuralSearcher(pdfdb.collection_name, pdfdb.client, pdfdb.encoder)
104+
transl = Translation(message, lan.replace("\\","").replace("'",""))
105+
message = transl.translatef()
106+
results = txt2txt.search(message)
107+
t = Translation(results[0]["text"], txt.original)
108+
res = t.translatef()
109+
response = runnable_with_history.invoke({"context": res, "input": message}, config={"configurable": {"session_id": sessionid}})##CONFIGURE!
110+
return response.content
111+
elif txt.original != "en" and lan.replace("\\","").replace("'","") == "None":
112+
txt2txt = NeuralSearcher(pdfdb.collection_name, pdfdb.client, pdfdb.encoder)
113+
results = txt2txt.search(message)
114+
transl = Translation(results[0]["text"], "en")
115+
translation = transl.translatef()
116+
response = runnable_with_history.invoke({"context": translation, "input": message}, config={"configurable": {"session_id": sessionid}})##CONFIGURE!
117+
t = Translation(response.content, txt.original)
118+
res = t.translatef()
119+
return res
120+
else:
121+
txt2txt = NeuralSearcher(pdfdb.collection_name, pdfdb.client, pdfdb.encoder)
122+
transl = Translation(message, lan.replace("\\","").replace("'",""))
123+
message = transl.translatef()
124+
results = txt2txt.search(message)
125+
t = Translation(results[0]["text"], txt.original)
126+
res = t.translatef()
127+
response = runnable_with_history.invoke({"context": res, "input": message}, config={"configurable": {"session_id": sessionid}})##CONFIGURE!
128+
tr = Translation(response.content, txt.original)
129+
ress = tr.translatef()
130+
return ress
131+
132+
chat_model = gr.Dropdown(
133+
[m for m in list(NAME2APIKEY)], label="Chat Model", info="Choose one of the available chat models"
134+
)
135+
136+
user_api_key = gr.Textbox(
137+
label="API key",
138+
info="Paste your API key here",
139+
lines=1,
140+
type="password",
141+
)
142+
143+
user_temperature = gr.Slider(0, 1, value=0.5, label="Temperature", info="Select model temperature")
144+
145+
user_max_new_tokens = gr.Slider(0, 8192, value=1024, label="Max new tokens", info="Select max output tokens (higher number of tokens will result in a longer latency)")
146+
147+
user_session_id = gr.Textbox(label="Session ID",info="This alphanumeric code will link model reply to a specific message history of which the models will be aware when replying. Changing it will result in the loss of memory for your model",value="1")
148+
149+
additional_accordion = gr.Accordion(label="Parameters to be set before you start chatting", open=True)
150+
151+
demo = gr.ChatInterface(fn=reply, additional_inputs=[chat_model, user_api_key, user_temperature, user_max_new_tokens, user_session_id], additional_inputs_accordion=additional_accordion, title="everything-ai-buildyourllm")
152+
153+
154+
if __name__=="__main__":
155+
demo.launch(server_name="0.0.0.0", share=False)

docker/llama_cpp_int.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
import requests
5757

5858
def llama_cpp_respond(query, max_new_tokens):
59-
url = "http://host.docker.internal:8000/completion"
59+
url = "http://localhost:8000/completion"
6060
headers = {
6161
"Content-Type": "application/json"
6262
}
@@ -77,7 +77,7 @@ def reply(max_new_tokens, message):
7777
if txt.original == "en" and lan.replace("\\","").replace("'","") == "None":
7878
txt2txt = NeuralSearcher(pdfdb.collection_name, pdfdb.client, pdfdb.encoder)
7979
results = txt2txt.search(message)
80-
response = llama_cpp_respond(results[0]["text"], max_new_tokens)
80+
response = llama_cpp_respond(f"Context: {results[0]["text"]}, prompt: {message}", max_new_tokens)
8181
return response
8282
elif txt.original == "en" and lan.replace("\\","").replace("'","") != "None":
8383
txt2txt = NeuralSearcher(pdfdb.collection_name, pdfdb.client, pdfdb.encoder)
@@ -86,14 +86,14 @@ def reply(max_new_tokens, message):
8686
results = txt2txt.search(message)
8787
t = Translation(results[0]["text"], txt.original)
8888
res = t.translatef()
89-
response = llama_cpp_respond(res, max_new_tokens)
89+
response = llama_cpp_respond(f"Context: {res}, prompt: {message}", max_new_tokens)
9090
return response
9191
elif txt.original != "en" and lan.replace("\\","").replace("'","") == "None":
9292
txt2txt = NeuralSearcher(pdfdb.collection_name, pdfdb.client, pdfdb.encoder)
9393
results = txt2txt.search(message)
9494
transl = Translation(results[0]["text"], "en")
9595
translation = transl.translatef()
96-
response = llama_cpp_respond(translation, max_new_tokens)
96+
response = llama_cpp_respond(f"Context: {translation}, prompt: {message}", max_new_tokens)
9797
t = Translation(response, txt.original)
9898
res = t.translatef()
9999
return res
@@ -104,7 +104,7 @@ def reply(max_new_tokens, message):
104104
results = txt2txt.search(message)
105105
t = Translation(results[0]["text"], txt.original)
106106
res = t.translatef()
107-
response = llama_cpp_respond(res, max_new_tokens)
107+
response = llama_cpp_respond(f"Context: {res}, prompt: {message}", max_new_tokens)
108108
tr = Translation(response, txt.original)
109109
ress = tr.translatef()
110110
return ress

docker/retrieval_text_generation.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def reply(message, history):
7373
if txt.original == "en" and lan.replace("\\","").replace("'","") == "None":
7474
txt2txt = NeuralSearcher(pdfdb.collection_name, pdfdb.client, pdfdb.encoder)
7575
results = txt2txt.search(message)
76-
response = pipe(results[0]["text"])
76+
response = pipe(f"Context: {results[0]["text"]}, prompt: {message}")
7777
return response[0]["generated_text"]
7878
elif txt.original == "en" and lan.replace("\\","").replace("'","") != "None":
7979
txt2txt = NeuralSearcher(pdfdb.collection_name, pdfdb.client, pdfdb.encoder)
@@ -82,14 +82,14 @@ def reply(message, history):
8282
results = txt2txt.search(message)
8383
t = Translation(results[0]["text"], txt.original)
8484
res = t.translatef()
85-
response = pipe(res)
85+
response = pipe(f"Context: {res}, prompt: {message}")
8686
return response[0]["generated_text"]
8787
elif txt.original != "en" and lan.replace("\\","").replace("'","") == "None":
8888
txt2txt = NeuralSearcher(pdfdb.collection_name, pdfdb.client, pdfdb.encoder)
8989
results = txt2txt.search(message)
9090
transl = Translation(results[0]["text"], "en")
9191
translation = transl.translatef()
92-
response = pipe(translation)
92+
response = pipe(f"Context: {translation}, prompt: {message}")
9393
t = Translation(response[0]["generated_text"], txt.original)
9494
res = t.translatef()
9595
return res
@@ -100,7 +100,7 @@ def reply(message, history):
100100
results = txt2txt.search(message)
101101
t = Translation(results[0]["text"], txt.original)
102102
res = t.translatef()
103-
response = pipe(res)
103+
response = pipe(f"Context: {res}, prompt: {message}")
104104
tr = Translation(response[0]["generated_text"], txt.original)
105105
ress = tr.translatef()
106106
return ress

docker/select_and_run.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import subprocess as sp
22
import gradio as gr
33

4-
TASK_TO_SCRIPT = {"retrieval-text-generation": "retrieval_text_generation.py", "agnostic-text-generation": "agnostic_text_generation.py", "text-summarization": "text_summarization.py", "image-generation": "image_generation.py", "image-generation-pollinations": "image_generation_pollinations.py", "image-classification": "image_classification.py", "image-to-text": "image_to_text.py", "retrieval-image-search": "retrieval_image_search.py", "protein-folding": "protein_folding_with_esm.py", "video-generation": "video_generation.py", "speech-recognition": "speech_recognition.py", "spaces-api-supabase": "spaces_api_supabase.py", "audio-classification": "audio_classification.py", "autotrain": "autotrain_interface.py", "llama.cpp-and-qdrant": "llama_cpp_int.py"}
4+
TASK_TO_SCRIPT = {"retrieval-text-generation": "retrieval_text_generation.py", "agnostic-text-generation": "agnostic_text_generation.py", "text-summarization": "text_summarization.py", "image-generation": "image_generation.py", "image-generation-pollinations": "image_generation_pollinations.py", "image-classification": "image_classification.py", "image-to-text": "image_to_text.py", "retrieval-image-search": "retrieval_image_search.py", "protein-folding": "protein_folding_with_esm.py", "video-generation": "video_generation.py", "speech-recognition": "speech_recognition.py", "spaces-api-supabase": "spaces_api_supabase.py", "audio-classification": "audio_classification.py", "autotrain": "autotrain_interface.py", "llama.cpp-and-qdrant": "llama_cpp_int.py", "build-your-llm": "build_your_llm.py"}
55

66

77
def build_command(tsk, mod="None", pdff="None", dirs="None", lan="None", imdim="512", gradioclient="None", supabaseurl="None", collectname="None", supenc="all-MiniLM-L6-v2", supdim="384"):
8-
if tsk != "retrieval-text-generation" and tsk != "image-generation-pollinations" and tsk != "retrieval-image-search" and tsk != "autotrain" and tsk != "protein-folding" and tsk != "spaces-api-supabase" and tsk != "llama.cpp-and-qdrant":
8+
if tsk != "retrieval-text-generation" and tsk != "image-generation-pollinations" and tsk != "retrieval-image-search" and tsk != "autotrain" and tsk != "protein-folding" and tsk != "spaces-api-supabase" and tsk != "llama.cpp-and-qdrant" and tsk!="build-your-llm":
99
sp.run(f"python3 {TASK_TO_SCRIPT[tsk]} -m {mod}", shell=True)
1010
return f"python3 {TASK_TO_SCRIPT[tsk]} -m {mod}"
1111
elif tsk == "retrieval-text-generation":
1212
sp.run(f"python3 {TASK_TO_SCRIPT[tsk]} -m {mod} -pf '{pdff}' -d '{dirs}' -l '{lan}'", shell=True)
1313
return f"python3 {TASK_TO_SCRIPT[tsk]} -m {mod} -pf '{pdff}' -d '{dirs}' -l '{lan}'"
14-
elif tsk == "llama.cpp-and-qdrant":
14+
elif tsk == "llama.cpp-and-qdrant" or tsk== "build-your-llm":
1515
sp.run(f"python3 {TASK_TO_SCRIPT[tsk]} -pf '{pdff}' -d '{dirs}' -l '{lan}'", shell=True)
1616
return f"python3 {TASK_TO_SCRIPT[tsk]} -pf '{pdff}' -d '{dirs}' -l '{lan}'"
1717
elif tsk == "image-generation-pollinations" or tsk == "autotrain" or tsk == "protein-folding":

imgs/everything-ai.drawio.png

66.4 KB
Loading

0 commit comments

Comments
 (0)