Spaces:
Sleeping
Sleeping
Commit
•
9c79212
1
Parent(s):
1ab7f5d
feat: update llm provider to groq and model to llama 3 8b
Browse files- Dockerfile +4 -2
- conf/.env.example +3 -0
- conf/params.yml +9 -5
- requirements.in +1 -0
- src/resume_worth/pipelines/text_generation/nodes.py +65 -17
- src/resume_worth/pipelines/text_generation/pipeline.py +5 -2
- src/resume_worth/utils/utils.py +17 -0
Dockerfile
CHANGED
@@ -21,6 +21,9 @@ ENV MPLCONFIGDIR=$MPLCONFIGDIR
|
|
21 |
ARG ENTRYPOINT_PATH="./entrypoint.sh"
|
22 |
ENV ENTRYPOINT_PATH=$ENTRYPOINT_PATH
|
23 |
|
|
|
|
|
|
|
24 |
# Create the /code/ directory a ser permissions rwe
|
25 |
RUN mkdir -p /code/&& \
|
26 |
chmod -R 777 /code/
|
@@ -55,7 +58,6 @@ COPY . .
|
|
55 |
RUN pip install -e . && \
|
56 |
python src/resume_worth/pipelines/data_indexing/pipeline.py
|
57 |
|
58 |
-
RUN
|
59 |
-
chmod +x $ENTRYPOINT_PATH
|
60 |
|
61 |
ENTRYPOINT $ENTRYPOINT_PATH
|
|
|
21 |
ARG ENTRYPOINT_PATH="./entrypoint.sh"
|
22 |
ENV ENTRYPOINT_PATH=$ENTRYPOINT_PATH
|
23 |
|
24 |
+
# RUN --mount=type=secret,id=GROQ_API_KEY,mode=0444,required=true \
|
25 |
+
# echo "GROQ_API_KEY=$(cat /run/secrets/GROQ_API_KEY)"
|
26 |
+
|
27 |
# Create the /code/ directory a ser permissions rwe
|
28 |
RUN mkdir -p /code/&& \
|
29 |
chmod -R 777 /code/
|
|
|
58 |
RUN pip install -e . && \
|
59 |
python src/resume_worth/pipelines/data_indexing/pipeline.py
|
60 |
|
61 |
+
RUN chmod +x $ENTRYPOINT_PATH
|
|
|
62 |
|
63 |
ENTRYPOINT $ENTRYPOINT_PATH
|
conf/.env.example
CHANGED
@@ -1,3 +1,6 @@
|
|
|
|
|
|
|
|
1 |
# OpenAI (to text generation)
|
2 |
OPENAI_API_KEY=""
|
3 |
OPENAI_ORG_ID=""
|
|
|
1 |
+
# Groq Cloud (to text generation)
|
2 |
+
GROQ_API_KEY="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"
|
3 |
+
|
4 |
# OpenAI (to text generation)
|
5 |
OPENAI_API_KEY=""
|
6 |
OPENAI_ORG_ID=""
|
conf/params.yml
CHANGED
@@ -1,3 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
1 |
# Data
|
2 |
ingestion_data_dir: ["data", "02_processed"]
|
3 |
ingestion_metadata_dir: ["data", "02_processed", "metadata"]
|
@@ -16,16 +21,15 @@ embedding_dir: ["data", "03_indexed"]
|
|
16 |
|
17 |
|
18 |
# LLM / Text Generation
|
|
|
19 |
# See instructions for parameters: https://www.ibm.com/docs/en/watsonx-as-a-service?topic=lab-model-parameters-prompting
|
20 |
generative_model:
|
21 |
-
|
|
|
22 |
model_kwargs:
|
23 |
-
trust_remote_code: True
|
24 |
-
generate_kwargs:
|
25 |
-
top_k: 30
|
26 |
top_p: 0.7
|
|
|
27 |
temperature: 0.3
|
28 |
-
max_new_tokens: 256
|
29 |
# See instructions for the prompt: https://huggingface.co/spaces/Locutusque/Locutusque-Models/blob/main/app.py
|
30 |
prompt_dir: ["data", "04_prompts"]
|
31 |
promp_file: "prompt_template_for_explaning_why_is_a_good_fit.json"
|
|
|
1 |
+
# Conf
|
2 |
+
conf_dir: ["conf"]
|
3 |
+
secrets_file: ".env"
|
4 |
+
|
5 |
+
|
6 |
# Data
|
7 |
ingestion_data_dir: ["data", "02_processed"]
|
8 |
ingestion_metadata_dir: ["data", "02_processed", "metadata"]
|
|
|
21 |
|
22 |
|
23 |
# LLM / Text Generation
|
24 |
+
# Suggestion: huggingface|M4-ai/tau-1.8B; groq|llama3-8b-8192
|
25 |
# See instructions for parameters: https://www.ibm.com/docs/en/watsonx-as-a-service?topic=lab-model-parameters-prompting
|
26 |
generative_model:
|
27 |
+
model_provider: "groq"
|
28 |
+
model_name: "llama3-8b-8192"
|
29 |
model_kwargs:
|
|
|
|
|
|
|
30 |
top_p: 0.7
|
31 |
+
generate_kwargs:
|
32 |
temperature: 0.3
|
|
|
33 |
# See instructions for the prompt: https://huggingface.co/spaces/Locutusque/Locutusque-Models/blob/main/app.py
|
34 |
prompt_dir: ["data", "04_prompts"]
|
35 |
promp_file: "prompt_template_for_explaning_why_is_a_good_fit.json"
|
requirements.in
CHANGED
@@ -7,6 +7,7 @@ pandas
|
|
7 |
# to build LLM Apps
|
8 |
langchain
|
9 |
langchain-community
|
|
|
10 |
sentence-transformers>=2.3.1
|
11 |
chromadb
|
12 |
|
|
|
7 |
# to build LLM Apps
|
8 |
langchain
|
9 |
langchain-community
|
10 |
+
langchain_groq
|
11 |
sentence-transformers>=2.3.1
|
12 |
chromadb
|
13 |
|
src/resume_worth/pipelines/text_generation/nodes.py
CHANGED
@@ -1,8 +1,11 @@
|
|
1 |
import os
|
2 |
os.environ['HF_HOME'] = ".cache/huggingface"
|
3 |
|
|
|
|
|
4 |
from langchain_community.llms.huggingface_pipeline import HuggingFacePipeline
|
5 |
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
|
|
|
6 |
from langchain_core.prompts import PromptTemplate
|
7 |
from langchain.prompts import load_prompt
|
8 |
from functools import lru_cache
|
@@ -13,26 +16,71 @@ transformers.logging.set_verbosity_error()
|
|
13 |
|
14 |
|
15 |
#@lru_cache(maxsize=None)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
def load_hf_text_generation_model_to_langchain(
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
):
|
28 |
"""
|
29 |
-
Function to load a text generation model hosted on Hugging Face to
|
30 |
More info, see: https://python.langchain.com/docs/integrations/llms/huggingface_pipelines/
|
31 |
"""
|
32 |
|
33 |
-
print(f"-> Load a pretrained text embedding model {model_name}")
|
34 |
-
|
35 |
-
# https://huggingface.co/apple/OpenELM
|
36 |
tokenizer = AutoTokenizer.from_pretrained(model_name, **model_kwargs)
|
37 |
model = AutoModelForCausalLM.from_pretrained(model_name, **model_kwargs)
|
38 |
|
@@ -68,10 +116,10 @@ def load_langchain_prompt_template(promp_path: str):
|
|
68 |
return prompt
|
69 |
|
70 |
|
71 |
-
def create_langchain_chain(prompt: PromptTemplate,
|
72 |
"""
|
73 |
-
Create a chain by composing the
|
74 |
More info, see: https://python.langchain.com/docs/integrations/llms/huggingface_pipelines/
|
75 |
"""
|
76 |
-
chain = prompt |
|
77 |
return chain
|
|
|
1 |
import os
|
2 |
os.environ['HF_HOME'] = ".cache/huggingface"
|
3 |
|
4 |
+
from typing import Union
|
5 |
+
from resume_worth.utils.utils import set_secrets
|
6 |
from langchain_community.llms.huggingface_pipeline import HuggingFacePipeline
|
7 |
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
|
8 |
+
from langchain_groq import ChatGroq
|
9 |
from langchain_core.prompts import PromptTemplate
|
10 |
from langchain.prompts import load_prompt
|
11 |
from functools import lru_cache
|
|
|
16 |
|
17 |
|
18 |
#@lru_cache(maxsize=None)
|
19 |
+
def load_text_generation_model(
|
20 |
+
model_provider:str='groq',
|
21 |
+
model_name:str='llama3-8b-8192',
|
22 |
+
model_kwargs:dict={},
|
23 |
+
generate_kwargs:dict={
|
24 |
+
'temperature': 0.4,
|
25 |
+
},
|
26 |
+
):
|
27 |
+
"""Function to load a text generation model according to the provider."""
|
28 |
+
|
29 |
+
print(f"-> Load {model_name} text generation model from {model_provider}")
|
30 |
+
|
31 |
+
if model_provider=="huggingface":
|
32 |
+
return load_hf_text_generation_model_to_langchain(model_name, model_kwargs, generate_kwargs)
|
33 |
+
|
34 |
+
elif model_provider=="groq":
|
35 |
+
set_secrets()
|
36 |
+
return load_groq_text_generation_model_to_langchain(model_name, model_kwargs, generate_kwargs)
|
37 |
+
|
38 |
+
else:
|
39 |
+
raise Exception("Sorry, the code has no support for this provider yet.")
|
40 |
+
|
41 |
+
|
42 |
+
def load_groq_text_generation_model_to_langchain(
|
43 |
+
model_name:str='llama3-8b-8192',
|
44 |
+
model_kwargs:dict={
|
45 |
+
'top_k': 50,
|
46 |
+
'top_p': 0.95,
|
47 |
+
'max_new_tokens': 1024,
|
48 |
+
},
|
49 |
+
generate_kwargs:dict={
|
50 |
+
'temperature': 0.4,
|
51 |
+
}
|
52 |
+
):
|
53 |
+
"""
|
54 |
+
Function to load a text generation model hosted on Groq to be used in LangChain.
|
55 |
+
More info, see: https://console.groq.com/docs/quickstart
|
56 |
+
"""
|
57 |
+
|
58 |
+
groq_api_key = os.environ.get('GROQ_API_KEY', None)
|
59 |
+
if groq_api_key is None:
|
60 |
+
raise ValueError("GROQ_API_KEY is not set.")
|
61 |
+
|
62 |
+
groq = ChatGroq(model_name=model_name, model_kwargs=model_kwargs, **generate_kwargs, groq_api_key=groq_api_key)
|
63 |
+
|
64 |
+
return groq
|
65 |
+
|
66 |
+
|
67 |
def load_hf_text_generation_model_to_langchain(
|
68 |
+
model_name:str='gpt2',
|
69 |
+
model_kwargs:dict={
|
70 |
+
'trust_remote_code': True,
|
71 |
+
},
|
72 |
+
generate_kwargs:dict={
|
73 |
+
'top_k': 50,
|
74 |
+
'top_p': 0.95,
|
75 |
+
'temperature': 0.4,
|
76 |
+
'max_new_tokens': 1024,
|
77 |
+
}
|
78 |
):
|
79 |
"""
|
80 |
+
Function to load a text generation model hosted on Hugging Face to be used in LangChain.
|
81 |
More info, see: https://python.langchain.com/docs/integrations/llms/huggingface_pipelines/
|
82 |
"""
|
83 |
|
|
|
|
|
|
|
84 |
tokenizer = AutoTokenizer.from_pretrained(model_name, **model_kwargs)
|
85 |
model = AutoModelForCausalLM.from_pretrained(model_name, **model_kwargs)
|
86 |
|
|
|
116 |
return prompt
|
117 |
|
118 |
|
119 |
+
def create_langchain_chain(prompt: PromptTemplate, text_generation_model: Union[HuggingFacePipeline, ChatGroq]):
|
120 |
"""
|
121 |
+
Create a chain by composing the text generation model with a LangChain prompt template.
|
122 |
More info, see: https://python.langchain.com/docs/integrations/llms/huggingface_pipelines/
|
123 |
"""
|
124 |
+
chain = prompt | text_generation_model
|
125 |
return chain
|
src/resume_worth/pipelines/text_generation/pipeline.py
CHANGED
@@ -7,7 +7,7 @@ This pipeline utilizes an LLM to explain why the retrieved job vacancy is a good
|
|
7 |
|
8 |
import os
|
9 |
from resume_worth.utils.utils import get_params
|
10 |
-
from resume_worth.pipelines.text_generation.nodes import
|
11 |
|
12 |
|
13 |
params = get_params()
|
@@ -20,7 +20,7 @@ def generate_explanation_why_resume_for_a_job(resume: str, job: str):
|
|
20 |
|
21 |
# Stage 1 - [cacheable] Load text generation model
|
22 |
|
23 |
-
text_generation_model =
|
24 |
|
25 |
# Stage 2 - [cacheable] Load text generation model
|
26 |
|
@@ -35,6 +35,9 @@ def generate_explanation_why_resume_for_a_job(resume: str, job: str):
|
|
35 |
|
36 |
answer = text_generation_chain.invoke({"resume": resume, "job": job})
|
37 |
|
|
|
|
|
|
|
38 |
return answer
|
39 |
|
40 |
|
|
|
7 |
|
8 |
import os
|
9 |
from resume_worth.utils.utils import get_params
|
10 |
+
from resume_worth.pipelines.text_generation.nodes import load_text_generation_model, load_langchain_prompt_template, create_langchain_chain
|
11 |
|
12 |
|
13 |
params = get_params()
|
|
|
20 |
|
21 |
# Stage 1 - [cacheable] Load text generation model
|
22 |
|
23 |
+
text_generation_model = load_text_generation_model(generative_model['model_provider'], generative_model['model_name'], generative_model['model_kwargs'], generative_model['generate_kwargs'])
|
24 |
|
25 |
# Stage 2 - [cacheable] Load text generation model
|
26 |
|
|
|
35 |
|
36 |
answer = text_generation_chain.invoke({"resume": resume, "job": job})
|
37 |
|
38 |
+
if generative_model['model_provider']!="huggingface":
|
39 |
+
answer = answer.content
|
40 |
+
|
41 |
return answer
|
42 |
|
43 |
|
src/resume_worth/utils/utils.py
CHANGED
@@ -4,6 +4,7 @@ os.environ['HF_HOME'] = ".cache/huggingface"
|
|
4 |
import yaml
|
5 |
from langchain_community.embeddings import HuggingFaceEmbeddings
|
6 |
import fitz # imports the pymupdf library
|
|
|
7 |
|
8 |
|
9 |
def get_params():
|
@@ -25,6 +26,22 @@ def get_params():
|
|
25 |
|
26 |
return params
|
27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
|
29 |
def load_embedding_model(model_name: str = "sentence-transformers/all-mpnet-base-v2", model_kwargs: dict={}, encode_kwargs: dict={}):
|
30 |
"""Load a pretrained text embedding model"""
|
|
|
4 |
import yaml
|
5 |
from langchain_community.embeddings import HuggingFaceEmbeddings
|
6 |
import fitz # imports the pymupdf library
|
7 |
+
from functools import lru_cache
|
8 |
|
9 |
|
10 |
def get_params():
|
|
|
26 |
|
27 |
return params
|
28 |
|
29 |
+
@lru_cache(maxsize=None)
|
30 |
+
def set_secrets():
|
31 |
+
"""
|
32 |
+
Function to set the secrets.
|
33 |
+
It load the parameters from .env file and set as env vars.
|
34 |
+
"""
|
35 |
+
params = get_params()
|
36 |
+
|
37 |
+
secrets_path = os.path.join(params['conf_dir'], params['secrets_file'])
|
38 |
+
|
39 |
+
if os.path.exists(secrets_path):
|
40 |
+
from dotenv import load_dotenv
|
41 |
+
_ = load_dotenv(secrets_path)
|
42 |
+
else:
|
43 |
+
print(f'The secret file {secrets_path} does not exist!')
|
44 |
+
|
45 |
|
46 |
def load_embedding_model(model_name: str = "sentence-transformers/all-mpnet-base-v2", model_kwargs: dict={}, encode_kwargs: dict={}):
|
47 |
"""Load a pretrained text embedding model"""
|