| import json |
| import os |
| from langchain_core.documents import Document |
| from langchain_huggingface import HuggingFaceEmbeddings |
| from dotenv import load_dotenv |
| from sentence_transformers import CrossEncoder |
| from langchain_core.messages import HumanMessage, AIMessage, BaseMessage |
|
|
| load_dotenv() |
|
|
| catalog_path = os.path.join(os.path.dirname(__file__),'data','catalog.json') |
|
|
| def load_catalog() -> list[dict]: |
| with open(catalog_path, "r", encoding="utf-8") as f: |
| return json.load(f) |
| |
| def create_document(catalog : list[dict]) -> list[Document]: |
| |
| docs = [] |
|
|
| for item in catalog: |
| text = f""" |
| Entity ID: {item.get('entity_id', '')} |
| |
| Assessment Name: {item.get('name', '')} |
| |
| Description: |
| {item.get('description', '')} |
| |
| Job Levels: |
| {', '.join(item.get('job_levels', []))} |
| |
| Languages: |
| {', '.join(item.get('languages', []))} |
| |
| Duration: |
| {item.get('duration', '')} |
| |
| Keys: |
| {', '.join(item.get('keys', []))} |
| |
| Remote Testing: |
| {item.get('remote', '')} |
| |
| Adaptive: |
| {item.get('adaptive', '')} |
| """ |
|
|
| metadata = { |
| "entity_id": item.get("entity_id"), |
| "name": item.get("name"), |
| "job_levels": item.get("job_levels", []), |
| "languages": item.get("languages", []), |
| "keys": item.get("keys", []), |
| "url": item.get("link") |
| } |
|
|
| docs.append(Document(page_content=text, metadata=metadata)) |
|
|
| return docs |
| |
| def download_embeddings(model_name="sentence-transformers/all-MiniLM-L6-v2") -> HuggingFaceEmbeddings: |
| embedding_model = HuggingFaceEmbeddings( |
| model_name="sentence-transformers/all-MiniLM-L6-v2", |
| cache_folder="./cache" |
| ) |
|
|
| return embedding_model |
|
|
| def download_reranker(model_name="cross-encoder/ms-marco-MiniLM-L-6-v2") -> CrossEncoder: |
| reranker = CrossEncoder(model_name,cache_folder="./cache") |
| return reranker |
|
|
| def deduplicate_docs(docs1,docs2): |
| return list({doc.metadata['entity_id']: doc for doc in docs1 + docs2}.values()) |
|
|
| def rerank_docs(reranker,query, docs,top_k=10): |
| pairs = [(query, doc.page_content) for doc in docs] |
| scores = reranker.predict(pairs) |
| ranked = sorted(zip(scores, docs), reverse=True) |
| return [doc for _, doc in ranked[:top_k]] |
|
|
| def convert_messages(messages) -> list[BaseMessage]: |
|
|
| lc_messages = [] |
|
|
| for msg in messages: |
|
|
| if msg.role == "user": |
|
|
| lc_messages.append( |
| HumanMessage(content=msg.content) |
| ) |
|
|
| elif msg.role == "assistant": |
|
|
| lc_messages.append( |
| AIMessage(content=msg.content) |
| ) |
|
|
| return lc_messages |
|
|
| def context_builder(docs : list[Document]) -> HumanMessage: |
|
|
| context_docs = "\n\n".join([f'{doc.page_content}' for doc in docs]) |
|
|
| context_msg = HumanMessage(content=f""" Retrieved SHL Assessments: {context_docs} |
| Use ONLY these retrieved assessments for reasoning, clarifications, comparisons and/or recommendation. """ ) |
| |
| return context_msg |