Spaces:
Sleeping
Sleeping
| import os | |
| import sys | |
| import json | |
| from typing import Dict, List, Any, Annotated | |
| from typing_extensions import TypedDict | |
| from langchain_core.messages import AIMessage, SystemMessage, HumanMessage | |
| from langgraph.graph import StateGraph, START, END | |
| from langgraph.graph.message import add_messages | |
| from langchain_openai import ChatOpenAI | |
| from src.config import read_system_prompt, format_cv | |
| class State(TypedDict): | |
| messages: Annotated[list, add_messages] | |
| class InterviewProcessor: | |
| def __init__(self, cv_document: Dict[str, Any], job_offer: Dict[str, Any], conversation_history: List[Dict[str, Any]]): | |
| if not cv_document or 'candidat' not in cv_document: | |
| raise ValueError("Document CV invalide fourni.") | |
| if not job_offer: | |
| raise ValueError("Données de l'offre d'emploi non fournies.") | |
| self.job_offer = job_offer | |
| self.cv_data = cv_document['candidat'] | |
| self.conversation_history = conversation_history | |
| self.llm = self._get_llm() | |
| self.system_prompt_template = self._load_prompt_template() | |
| self.graph = self._build_graph() | |
| def _get_llm(self) -> ChatOpenAI: | |
| openai_api_key = os.getenv("OPENAI_API_KEY") | |
| return ChatOpenAI( | |
| temperature=0.6, | |
| model_name="gpt-4o-mini", | |
| api_key=openai_api_key | |
| ) | |
| def _load_prompt_template(self) -> str: | |
| return read_system_prompt('prompts/rag_prompt_old.txt') | |
| def _extract_skills_summary(self) -> str: | |
| """Extrait un résumé simple des compétences avec niveaux""" | |
| competences = self.cv_data.get('analyse_competences', []) | |
| if not competences: | |
| return "Aucune analyse de compétences disponible." | |
| summary = [] | |
| for comp in competences: | |
| skill = comp.get('skill', '') | |
| level = comp.get('level', 'débutant') | |
| summary.append(f"{skill}: {level}") | |
| return "Niveaux de compétences du candidat: " + " | ".join(summary) | |
| def _extract_reconversion_info(self) -> str: | |
| """Extrait les infos de reconversion""" | |
| reconversion = self.cv_data.get('reconversion', {}) | |
| if not reconversion: | |
| return "" | |
| is_reconversion = reconversion.get('is_reconversion', False) | |
| if not is_reconversion: | |
| return "" | |
| analysis = reconversion.get('analysis', '') | |
| return f"CANDIDAT EN RECONVERSION: {analysis}" | |
| def _chatbot_node(self, state: State) -> dict: | |
| messages = state["messages"] | |
| formatted_cv_str = format_cv(self.cv_data) | |
| # Extractions simples | |
| skills_summary = self._extract_skills_summary() | |
| reconversion_info = self._extract_reconversion_info() | |
| # Formatage du prompt système avec les nouvelles données | |
| system_prompt = self.system_prompt_template.format( | |
| entreprise=self.job_offer.get('entreprise', 'notre entreprise'), | |
| poste=self.job_offer.get('poste', 'ce poste'), | |
| mission=self.job_offer.get('mission', 'Non spécifiée'), | |
| profil_recherche=self.job_offer.get('profil_recherche', 'Non spécifié'), | |
| competences=self.job_offer.get('competences', 'Non spécifiées'), | |
| pole=self.job_offer.get('pole', 'Non spécifié'), | |
| cv=formatted_cv_str, | |
| skills_analysis=skills_summary, | |
| reconversion_analysis=reconversion_info | |
| ) | |
| llm_messages = [SystemMessage(content=system_prompt)] + messages | |
| response = self.llm.invoke(llm_messages) | |
| return {"messages": [response]} | |
| def _build_graph(self) -> any: | |
| graph_builder = StateGraph(State) | |
| graph_builder.add_node("chatbot", self._chatbot_node) | |
| graph_builder.add_edge(START, "chatbot") | |
| graph_builder.add_edge("chatbot", END) | |
| return graph_builder.compile() | |
| def run(self, messages: List[Dict[str, Any]]) -> Dict[str, Any]: | |
| initial_state = self.conversation_history + messages | |
| return self.graph.invoke({"messages": initial_state}) |