Spaces:
Sleeping
Sleeping
File size: 5,646 Bytes
478dec6 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | import asyncio
import os, sys
import time
from dotenv import load_dotenv
load_dotenv()
from typing import AsyncIterable
from typing import List, Optional, Dict
from langchain.schema import HumanMessage, AIMessage
from langchain.callbacks import AsyncIteratorCallbackHandler
# from fastapi.middleware.cors import CORSMiddleware
# from fastapi.responses import StreamingResponse
# from langchain.chat_models import ChatOpenAI
# from pydantic import BaseModel
# from langchain_google_genai import ChatGoogleGenerativeAI
from models.data_model import OutProfile, OutMatching
from services.llms.LLM import model_gemini, model_4o, model_4omini, model_5mini
from services.agents.LLMAgent import LLMAgent
from services.prompts.profile_matching import match_one_profile
from utils.utils import pdf_reader, ingest_one_profile, ingest_bulk_profile
async def helper_profile_match_prompt(profile: OutProfile) -> str:
profile.high_edu_major_1 = profile.high_edu_major_1 if profile.high_edu_major_1 else "-"
profile.high_edu_univ_1 = profile.high_edu_univ_1 if profile.high_edu_univ_1 else "-"
profile.high_edu_gpa_1 = profile.high_edu_gpa_1 if profile.high_edu_gpa_1 else "-"
profile.high_edu_major_2 = profile.high_edu_major_2 if profile.high_edu_major_2 else "-"
profile.high_edu_univ_2 = profile.high_edu_univ_2 if profile.high_edu_univ_2 else "-"
profile.high_edu_gpa_2 = profile.high_edu_gpa_2 if profile.high_edu_gpa_2 else "-"
profile.high_edu_major_3 = profile.high_edu_major_3 if profile.high_edu_major_3 else "-"
profile.high_edu_univ_3 = profile.high_edu_univ_3 if profile.high_edu_univ_3 else "-"
profile.high_edu_gpa_3 = profile.high_edu_gpa_3 if profile.high_edu_gpa_3 else "-"
profile.hardskills = profile.hardskills if profile.hardskills else []
profile.softskills = profile.softskills if profile.softskills else []
profile.certifications = profile.certifications if profile.certifications else []
profile.business_domain_experiences = profile.business_domain_experiences if profile.business_domain_experiences else []
profile_text = f"""
# Candidate Profile
**Education**
- Bachelor degree major: {profile.high_edu_major_1 or "-"}
- Bachelor university: {profile.high_edu_univ_1 or "-"}
- Bachelor GPA: {profile.high_edu_gpa_1 or "-"}
- Master degree major: {profile.high_edu_major_2 or "-"}
- Master university: {profile.high_edu_univ_2 or "-"}
- Master GPA: {profile.high_edu_gpa_2 or "-"}
- Doctor/Phd degree major: {profile.high_edu_major_3 or "-"}
- Doctor/Phd university: {profile.high_edu_univ_3 or "-"}
- Doctor/Phd GPA: {profile.high_edu_gpa_3 or "-"}
**Year of Working Experience**
{profile.yoe} year
**Hardskills**
{", ".join([p for p in profile.hardskills if p not in ['null', '']])}
**Softskills**
{", ".join([p for p in profile.softskills if p not in ['null', '']])}
**Certifications**
{", ".join([p for p in profile.certifications if p not in ['null', '']])}
**Business domain experiences**
{", ".join([p for p in profile.business_domain_experiences if p not in ['null', '']])}
""".strip()
return profile_text
class ProfileMatchingAgent(LLMAgent):
def __init__(self, model=model_5mini):
super().__init__(model)
self.agent_name = "ProfileMatchingAgent"
self.prompt_template = match_one_profile
async def _helper_matching_one(self, profile_id:int, profile_dict:Dict, profile_text:str, criteria:str) -> Dict:
llm = self.model.with_structured_output(OutMatching)
chain = self.prompt_template | llm
input_chain = {
"profile_text":profile_text,
"criteria":criteria,
}
matched_profile = await chain.ainvoke(input_chain, config=None)
print(f"_helper_matching_one/matched_profile:\n{matched_profile}")
# matched_profile = matched_profile.model_dump()
# matched_profile["profile_id"] = profile_id
profile_dict["score"] = matched_profile.score
profile_dict["reason"] = matched_profile.reason
profile_dict["profile_id"] = profile_id
return profile_dict
async def matching_profile_bulk(self, profiles:List[OutProfile], criteria:str) -> Optional[List]:
try:
st = time.time()
tasks = []
profiles_text = []
profiles_dict = []
n_profiles = len(profiles)
for profile_id, p in enumerate(profiles):
print(f"Processing [{profile_id+1}/{n_profiles}]")
profile_text = await helper_profile_match_prompt(p)
profile_dict = p.model_dump()
profiles_dict.append(profile_dict)
profiles_text.append(profile_text)
task = asyncio.create_task(self._helper_matching_one(profile_id=profile_id,
profile_dict=profile_dict,
profile_text=profile_text,
criteria=criteria))
tasks.append(task)
profiles_with_scores = await asyncio.gather(*tasks)
print(f"✅ Profile matching finished in {(time.time() - st)//60} min, {(time.time() - st)%60} sec")
return profiles_with_scores
except Exception as E:
error_message = f"Processing profile matching error: {E}"
print(error_message)
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(exc_type, fname, exc_tb.tb_lineno)
|