QuentinL52 commited on
Commit
d426b96
·
verified ·
1 Parent(s): 16cd81d

Update services/graph_service.py

Browse files
Files changed (1) hide show
  1. services/graph_service.py +11 -18
services/graph_service.py CHANGED
@@ -4,16 +4,15 @@ import json
4
  from typing import TypedDict, Annotated, Sequence, Dict, Any, List
5
 
6
  from langchain_openai import ChatOpenAI
 
7
  from langchain_core.messages import BaseMessage, AIMessage, HumanMessage, SystemMessage
8
- from langchain.agents import create_openai_tools_agent, AgentExecutor
9
  from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
10
- # Nouveaux imports pour la gestion correcte du graphe
11
  from langgraph.graph import StateGraph, END
12
  from langgraph.prebuilt import ToolNode
13
 
14
  from tools.analysis_tools import trigger_interview_analysis
15
 
16
-
17
  class AgentState(TypedDict):
18
  messages: Annotated[Sequence[BaseMessage], lambda x, y: x + y]
19
  user_id: str
@@ -40,7 +39,7 @@ class GraphInterviewProcessor:
40
  self.skills_summary = self._extract_skills_summary()
41
  self.reconversion_info = self._extract_reconversion_info()
42
 
43
- self.agent_executor = self._create_agent_executor()
44
  self.graph = self._build_graph()
45
  logging.info("GraphInterviewProcessor initialisé avec succès.")
46
 
@@ -67,7 +66,7 @@ class GraphInterviewProcessor:
67
  return f"CANDIDAT EN RECONVERSION: {reconversion.get('analysis', '')}"
68
  return "Le candidat n'est pas identifié comme étant en reconversion."
69
 
70
- def _create_agent_executor(self) -> AgentExecutor:
71
  prompt = ChatPromptTemplate.from_messages([
72
  SystemMessage(content="{system_prompt_content}"),
73
  MessagesPlaceholder(variable_name="messages"),
@@ -75,10 +74,10 @@ class GraphInterviewProcessor:
75
  ])
76
  llm = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"), model="gpt-4o-mini", temperature=0.7)
77
  tools = [trigger_interview_analysis]
78
- agent = create_openai_tools_agent(llm, tools, prompt)
79
- return AgentExecutor(agent=agent, tools=tools, verbose=True)
80
 
81
  def _agent_node(self, state: AgentState):
 
82
  system_prompt_content = self.system_prompt_template.format(
83
  entreprise=self.job_offer.get('entreprise', 'notre entreprise'),
84
  poste=self.job_offer.get('poste', 'ce poste'),
@@ -91,14 +90,13 @@ class GraphInterviewProcessor:
91
  reconversion_analysis=self.reconversion_info
92
  )
93
 
94
- response = self.agent_executor.invoke({
95
  "system_prompt_content": system_prompt_content,
96
  "messages": state["messages"],
97
  "user_id": state["user_id"],
98
  "job_offer_id": state["job_offer_id"],
99
- "conversation_history": state["messages"]
100
  })
101
- return {"messages": [response['output']]}
102
 
103
  def _router(self, state: AgentState):
104
  """Décide du chemin à suivre après la réponse de l'agent."""
@@ -126,7 +124,7 @@ class GraphInterviewProcessor:
126
  "end_turn": END
127
  }
128
  )
129
-
130
  graph.add_edge("tools", "agent")
131
 
132
  return graph.compile()
@@ -141,24 +139,19 @@ class GraphInterviewProcessor:
141
  "messages": langchain_messages,
142
  }
143
 
144
- logging.info(f"Invoking graph with initial state: {initial_state}")
145
  final_state = self.graph.invoke(initial_state)
146
-
147
- logging.info(f"Graph finished. Final state: {final_state}")
148
 
149
  if not final_state or not final_state.get('messages'):
150
- logging.error("Final state is empty or does not contain messages.")
151
  return {"response": "Erreur: Impossible de générer une réponse.", "status": "finished"}
152
 
153
  last_message = final_state['messages'][-1]
154
- logging.info(f"Last message from graph: {last_message}")
155
 
156
  status = "finished" if hasattr(last_message, 'tool_calls') and last_message.tool_calls else "interviewing"
157
 
158
  response_content = last_message.content
159
- logging.info(f"Final response content: '{response_content}', status: {status}")
160
 
161
  return {
162
  "response": response_content,
163
  "status": status
164
- }
 
4
  from typing import TypedDict, Annotated, Sequence, Dict, Any, List
5
 
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.agents import create_openai_tools_agent
10
  from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
 
11
  from langgraph.graph import StateGraph, END
12
  from langgraph.prebuilt import ToolNode
13
 
14
  from tools.analysis_tools import trigger_interview_analysis
15
 
 
16
  class AgentState(TypedDict):
17
  messages: Annotated[Sequence[BaseMessage], lambda x, y: x + y]
18
  user_id: str
 
39
  self.skills_summary = self._extract_skills_summary()
40
  self.reconversion_info = self._extract_reconversion_info()
41
 
42
+ self.agent = self._create_agent()
43
  self.graph = self._build_graph()
44
  logging.info("GraphInterviewProcessor initialisé avec succès.")
45
 
 
66
  return f"CANDIDAT EN RECONVERSION: {reconversion.get('analysis', '')}"
67
  return "Le candidat n'est pas identifié comme étant en reconversion."
68
 
69
+ def _create_agent(self) -> Runnable:
70
  prompt = ChatPromptTemplate.from_messages([
71
  SystemMessage(content="{system_prompt_content}"),
72
  MessagesPlaceholder(variable_name="messages"),
 
74
  ])
75
  llm = ChatOpenAI(api_key=os.getenv("OPENAI_API_KEY"), model="gpt-4o-mini", temperature=0.7)
76
  tools = [trigger_interview_analysis]
77
+ return create_openai_tools_agent(llm, tools, prompt)
 
78
 
79
  def _agent_node(self, state: AgentState):
80
+ """Prépare le prompt et appelle l'agent pour obtenir une décision (parler ou utiliser un outil)."""
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'),
 
90
  reconversion_analysis=self.reconversion_info
91
  )
92
 
93
+ response = self.agent.invoke({
94
  "system_prompt_content": system_prompt_content,
95
  "messages": state["messages"],
96
  "user_id": state["user_id"],
97
  "job_offer_id": state["job_offer_id"],
 
98
  })
99
+ return {"messages": [response]}
100
 
101
  def _router(self, state: AgentState):
102
  """Décide du chemin à suivre après la réponse de l'agent."""
 
124
  "end_turn": END
125
  }
126
  )
127
+
128
  graph.add_edge("tools", "agent")
129
 
130
  return graph.compile()
 
139
  "messages": langchain_messages,
140
  }
141
 
 
142
  final_state = self.graph.invoke(initial_state)
 
 
143
 
144
  if not final_state or not final_state.get('messages'):
145
+ logging.error("L'état final est vide ou ne contient pas de messages.")
146
  return {"response": "Erreur: Impossible de générer une réponse.", "status": "finished"}
147
 
148
  last_message = final_state['messages'][-1]
 
149
 
150
  status = "finished" if hasattr(last_message, 'tool_calls') and last_message.tool_calls else "interviewing"
151
 
152
  response_content = last_message.content
 
153
 
154
  return {
155
  "response": response_content,
156
  "status": status
157
+ }