from collections.abc import Callable from Levenshtein import ratio from template_project.application.common.unit_of_work import UnitOfWork from template_project.application.resume.data_gateway import ResumeDataGateway from template_project.application.resume.entity import Resume, ResumeEmbedding, ResumePrediction from template_project.application.resume.vector_generator import ResumeEmbeddingVectorGenerator def suitable_resumes_key( resume: Resume, ) -> Callable[[Resume], bool]: def wrapper(suitable_resume: Resume) -> bool: count_skills = 0 ratio_skill_sum = 0.0 for resum_key_skill in resume.key_skills: for suitable_resume_key_skill in suitable_resume.key_skills: ratio_skill = ratio(resum_key_skill, suitable_resume_key_skill) if ratio_skill != 0: count_skills += 1 ratio_skill_sum += ratio_skill try: matching_skills = ratio_skill_sum / count_skills except ZeroDivisionError: matching_skills = 0 return resume.experience_type == suitable_resume.experience_type and matching_skills >= 50 return wrapper class ResumeEmbeddingPipeline: def __init__( self, unit_of_work: UnitOfWork, resume_data_gateway: ResumeDataGateway, vector_generator: ResumeEmbeddingVectorGenerator, ) -> None: self.unit_of_work = unit_of_work self.resume_data_gateway = resume_data_gateway self.vector_generator = vector_generator async def run( self, resume: Resume, ) -> ResumePrediction: vector = await self.vector_generator.generate( position=resume.position, about_me=resume.about_me, key_skills=resume.key_skills, ) resume_embedding = ResumeEmbedding.factory( resume_id=resume.id, vector=vector, ) suitable_resumes = await self.resume_data_gateway.get_suitable_resumes(resume_embedding.id) suitable_resumes_filtered = sorted( suitable_resumes, key=suitable_resumes_key(resume), ) suitable_resumes = suitable_resumes_filtered[:50] # TODO: тут надо сделать отправку в ИИ await self.unit_of_work.add(resume_embedding) await self.unit_of_work.commit() raise NotImplementedError