Spaces:
Sleeping
Sleeping
Update services/graph_service.py
Browse files- services/graph_service.py +19 -6
services/graph_service.py
CHANGED
|
@@ -6,7 +6,6 @@ from typing import TypedDict, Annotated, Sequence, Dict, Any, List
|
|
| 6 |
from langchain_openai import ChatOpenAI
|
| 7 |
from langchain_core.runnables import Runnable
|
| 8 |
from langchain_core.messages import BaseMessage, AIMessage, HumanMessage, SystemMessage
|
| 9 |
-
# create_openai_tools_agent n'est plus nécessaire
|
| 10 |
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
| 11 |
from langgraph.graph import StateGraph, END
|
| 12 |
from langgraph.prebuilt import ToolNode
|
|
@@ -17,7 +16,7 @@ class AgentState(TypedDict):
|
|
| 17 |
messages: Annotated[Sequence[BaseMessage], lambda x, y: x + y]
|
| 18 |
user_id: str
|
| 19 |
job_offer_id: str
|
| 20 |
-
|
| 21 |
class GraphInterviewProcessor:
|
| 22 |
"""
|
| 23 |
Cette classe encapsule la logique d'un entretien en utilisant LangGraph.
|
|
@@ -65,6 +64,7 @@ class GraphInterviewProcessor:
|
|
| 65 |
if reconversion.get('is_reconversion'):
|
| 66 |
return f"CANDIDAT EN RECONVERSION: {reconversion.get('analysis', '')}"
|
| 67 |
return "Le candidat n'est pas identifié comme étant en reconversion."
|
|
|
|
| 68 |
def _create_agent_runnable(self) -> Runnable:
|
| 69 |
"""Crée une chaîne (runnable) qui agit comme notre agent."""
|
| 70 |
prompt = ChatPromptTemplate.from_messages([
|
|
@@ -74,10 +74,20 @@ class GraphInterviewProcessor:
|
|
| 74 |
llm = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"), model="gpt-4o-mini", temperature=0.7)
|
| 75 |
tools = [trigger_interview_analysis]
|
| 76 |
llm_with_tools = llm.bind_tools(tools)
|
|
|
|
| 77 |
return prompt | llm_with_tools
|
| 78 |
|
| 79 |
def _agent_node(self, state: AgentState):
|
| 80 |
"""Prépare le prompt et appelle le runnable de l'agent."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
system_prompt_content = self.system_prompt_template.format(
|
| 82 |
entreprise=self.job_offer.get('entreprise', 'notre entreprise'),
|
| 83 |
poste=self.job_offer.get('poste', 'ce poste'),
|
|
@@ -89,9 +99,14 @@ class GraphInterviewProcessor:
|
|
| 89 |
skills_analysis=self.skills_summary,
|
| 90 |
reconversion_analysis=self.reconversion_info
|
| 91 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 92 |
response = self.agent_runnable.invoke({
|
| 93 |
-
"system_prompt_content":
|
| 94 |
"messages": state["messages"],
|
|
|
|
| 95 |
})
|
| 96 |
return {"messages": [response]}
|
| 97 |
|
|
@@ -147,12 +162,10 @@ class GraphInterviewProcessor:
|
|
| 147 |
return {"response": "Erreur: Impossible de générer une réponse.", "status": "finished"}
|
| 148 |
|
| 149 |
last_message = final_state['messages'][-1]
|
| 150 |
-
|
| 151 |
status = "finished" if hasattr(last_message, 'tool_calls') and last_message.tool_calls else "interviewing"
|
| 152 |
-
|
| 153 |
response_content = last_message.content
|
| 154 |
|
| 155 |
return {
|
| 156 |
"response": response_content,
|
| 157 |
"status": status
|
| 158 |
-
}
|
|
|
|
| 6 |
from langchain_openai import ChatOpenAI
|
| 7 |
from langchain_core.runnables import Runnable
|
| 8 |
from langchain_core.messages import BaseMessage, AIMessage, HumanMessage, SystemMessage
|
|
|
|
| 9 |
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
| 10 |
from langgraph.graph import StateGraph, END
|
| 11 |
from langgraph.prebuilt import ToolNode
|
|
|
|
| 16 |
messages: Annotated[Sequence[BaseMessage], lambda x, y: x + y]
|
| 17 |
user_id: str
|
| 18 |
job_offer_id: str
|
| 19 |
+
|
| 20 |
class GraphInterviewProcessor:
|
| 21 |
"""
|
| 22 |
Cette classe encapsule la logique d'un entretien en utilisant LangGraph.
|
|
|
|
| 64 |
if reconversion.get('is_reconversion'):
|
| 65 |
return f"CANDIDAT EN RECONVERSION: {reconversion.get('analysis', '')}"
|
| 66 |
return "Le candidat n'est pas identifié comme étant en reconversion."
|
| 67 |
+
|
| 68 |
def _create_agent_runnable(self) -> Runnable:
|
| 69 |
"""Crée une chaîne (runnable) qui agit comme notre agent."""
|
| 70 |
prompt = ChatPromptTemplate.from_messages([
|
|
|
|
| 74 |
llm = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"), model="gpt-4o-mini", temperature=0.7)
|
| 75 |
tools = [trigger_interview_analysis]
|
| 76 |
llm_with_tools = llm.bind_tools(tools)
|
| 77 |
+
|
| 78 |
return prompt | llm_with_tools
|
| 79 |
|
| 80 |
def _agent_node(self, state: AgentState):
|
| 81 |
"""Prépare le prompt et appelle le runnable de l'agent."""
|
| 82 |
+
|
| 83 |
+
context_header = (
|
| 84 |
+
f"--- CONTEXTE TECHNIQUE POUR L'AGENT (ne pas mentionner à l'utilisateur) ---\n"
|
| 85 |
+
f"L'ID de l'utilisateur actuel est : {state['user_id']}\n"
|
| 86 |
+
f"L'ID de l'offre d'emploi actuelle est : {state['job_offer_id']}\n"
|
| 87 |
+
f"Quand tu appelleras l'outil 'trigger_interview_analysis', tu devras OBLIGATOIREMENT utiliser ces IDs exacts.\n"
|
| 88 |
+
f"--- FIN DU CONTEXTE TECHNIQUE ---\n\n"
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
system_prompt_content = self.system_prompt_template.format(
|
| 92 |
entreprise=self.job_offer.get('entreprise', 'notre entreprise'),
|
| 93 |
poste=self.job_offer.get('poste', 'ce poste'),
|
|
|
|
| 99 |
skills_analysis=self.skills_summary,
|
| 100 |
reconversion_analysis=self.reconversion_info
|
| 101 |
)
|
| 102 |
+
|
| 103 |
+
final_system_prompt = context_header + system_prompt_content
|
| 104 |
+
job_description = json.dumps(self.job_offer)
|
| 105 |
+
|
| 106 |
response = self.agent_runnable.invoke({
|
| 107 |
+
"system_prompt_content": final_system_prompt,
|
| 108 |
"messages": state["messages"],
|
| 109 |
+
"job_description": job_description
|
| 110 |
})
|
| 111 |
return {"messages": [response]}
|
| 112 |
|
|
|
|
| 162 |
return {"response": "Erreur: Impossible de générer une réponse.", "status": "finished"}
|
| 163 |
|
| 164 |
last_message = final_state['messages'][-1]
|
|
|
|
| 165 |
status = "finished" if hasattr(last_message, 'tool_calls') and last_message.tool_calls else "interviewing"
|
|
|
|
| 166 |
response_content = last_message.content
|
| 167 |
|
| 168 |
return {
|
| 169 |
"response": response_content,
|
| 170 |
"status": status
|
| 171 |
+
}
|