datacipen commited on
Commit
1b28be9
·
verified ·
1 Parent(s): 9206114

Update agent_collaboratif_avid.py

Browse files
Files changed (1) hide show
  1. agent_collaboratif_avid.py +80 -3
agent_collaboratif_avid.py CHANGED
@@ -36,6 +36,7 @@ from langgraph.prebuilt import ToolNode
36
 
37
  from pinecone import Pinecone
38
  import asyncio
 
39
 
40
  # =============================================================================
41
  # CONFIGURATION GLOBALE
@@ -43,6 +44,7 @@ import asyncio
43
 
44
  # Configuration API
45
  PINECONE_API_KEY = os.environ.get("PINECONE_API_KEY")
 
46
  #OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
47
  #OPENAI_BASE_URL = os.environ.get("OPENAI_BASE_URL")
48
  #OPENAI_MODEL_NAME = os.environ.get("OPENAI_MODEL_NAME")
@@ -64,6 +66,8 @@ if not PINECONE_API_KEY:
64
  raise ValueError("❌ PINECONE_API_KEY non définie. Exécutez: export PINECONE_API_KEY='votre-clé'")
65
  if not OPENAI_API_KEY:
66
  raise ValueError("❌ OPENAI_API_KEY non définie. Exécutez: export OPENAI_API_KEY='votre-clé'")
 
 
67
 
68
  # =============================================================================
69
  # EMBEDDINGS HUGGINGFACE
@@ -131,6 +135,7 @@ class AgentState(TypedDict):
131
  errors: List[str]
132
  additional_information: List[Dict[str, Any]] # Nouvelles infos similaires
133
  similar_info_response: str # Réponse LLM basée sur les informations similaires
 
134
 
135
  # =============================================================================
136
  # INITIALISATION DES RETRIEVERS PINECONE
@@ -707,6 +712,61 @@ def collect_similar_information_node(state: AgentState) -> AgentState:
707
 
708
  return state
709
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
710
  # =============================================================================
711
  # FONCTIONS DE ROUTAGE
712
  # =============================================================================
@@ -763,6 +823,7 @@ def create_agent_workflow() -> StateGraph:
763
  workflow.add_node("validate_response", validate_response_node)
764
  workflow.add_node("refine_response", refine_response_node)
765
  workflow.add_node("collect_similar_information", collect_similar_information_node)
 
766
 
767
  workflow.set_entry_point("analyze_query")
768
 
@@ -803,7 +864,8 @@ def create_agent_workflow() -> StateGraph:
803
  )
804
 
805
  workflow.add_edge("refine_response", "validate_response")
806
- workflow.add_edge("collect_similar_information", END)
 
807
 
808
  #memory = MemorySaver()
809
  #app = workflow.compile(checkpointer=memory)
@@ -836,7 +898,8 @@ async def run_collaborative_agent(user_query: str) -> Dict[str, Any]:
836
  "final_response": "",
837
  "iteration_count": 0,
838
  "errors": [],
839
- "additional_information": []
 
840
  }
841
 
842
  print(f"{'='*80}")
@@ -859,8 +922,9 @@ async def run_collaborative_agent(user_query: str) -> Dict[str, Any]:
859
  "iteration_count": final_state.get("iteration_count", 0),
860
  "errors": final_state.get("errors", []),
861
  "additional_information": final_state.get("additional_information", []),
 
862
  "sources_used": [
863
- info["database"]
864
  for info in final_state.get("collected_information", [])
865
  ],
866
  "pinecone_index": PINECONE_INDEX_NAME
@@ -1055,6 +1119,19 @@ def display_results(result: Dict[str, Any]) -> None:
1055
  print(result['similar_info_response'])
1056
  print()
1057
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1058
  async def main():
1059
  """Fonction principale de l'application."""
1060
 
 
36
 
37
  from pinecone import Pinecone
38
  import asyncio
39
+ from tavily import TavilyClient
40
 
41
  # =============================================================================
42
  # CONFIGURATION GLOBALE
 
44
 
45
  # Configuration API
46
  PINECONE_API_KEY = os.environ.get("PINECONE_API_KEY")
47
+ TAVILY_API_KEY = os.environ.get("TAVILY_API_KEY")
48
  #OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
49
  #OPENAI_BASE_URL = os.environ.get("OPENAI_BASE_URL")
50
  #OPENAI_MODEL_NAME = os.environ.get("OPENAI_MODEL_NAME")
 
66
  raise ValueError("❌ PINECONE_API_KEY non définie. Exécutez: export PINECONE_API_KEY='votre-clé'")
67
  if not OPENAI_API_KEY:
68
  raise ValueError("❌ OPENAI_API_KEY non définie. Exécutez: export OPENAI_API_KEY='votre-clé'")
69
+ if not TAVILY_API_KEY:
70
+ raise ValueError("❌ TAVILY_API_KEY non définie. Exécutez: export TAVILY_API_KEY='votre-clé'")
71
 
72
  # =============================================================================
73
  # EMBEDDINGS HUGGINGFACE
 
135
  errors: List[str]
136
  additional_information: List[Dict[str, Any]] # Nouvelles infos similaires
137
  similar_info_response: str # Réponse LLM basée sur les informations similaires
138
+ web_search_results: List[Dict[str, Any]] # Résultats de la recherche web
139
 
140
  # =============================================================================
141
  # INITIALISATION DES RETRIEVERS PINECONE
 
712
 
713
  return state
714
 
715
+ # =============================================================================
716
+ # NODE 7: RECHERCHE WEB (TAVILY)
717
+ # =============================================================================
718
+
719
+ def web_search_node(state: AgentState) -> AgentState:
720
+ """
721
+ Node de recherche web utilisant Tavily Search.
722
+ Recherche sur le web en fonction de la requête utilisateur analysée.
723
+ """
724
+ print(f"\n{'='*80}")
725
+ print(f"🌐 NODE 7: RECHERCHE WEB (TAVILY)")
726
+ print(f"{'='*80}\n")
727
+
728
+ # Initialiser le client Tavily
729
+ tavily = TavilyClient(api_key=TAVILY_API_KEY)
730
+
731
+ user_query = state["user_query"]
732
+ web_search_results = []
733
+
734
+ try:
735
+ print(f"🔍 Exécution de la recherche web pour: '{user_query}'...")
736
+ # Effectuer la recherche web, obtenir les 5 meilleurs résultats
737
+ response = tavily.search(query="Université Gustave Eiffel + " + user_query, search_depth="advanced", max_results=5, include_raw_content=False)
738
+
739
+ if response and response['results']:
740
+ print(f"✅ {len(response['results'])} résultats trouvés.")
741
+ for i, result in enumerate(response['results']):
742
+ title = result.get('title', 'Titre inconnu')
743
+ url = result.get('url', '#')
744
+ content = result.get('content', 'Contenu non disponible')
745
+
746
+ # Résumé en 2 phrases
747
+ sentences = content.split('.')
748
+ summary = ". ".join(sentences[:2]) + ("." if len(sentences) > 2 else "")
749
+
750
+ web_search_results.append({
751
+ "title": title,
752
+ "url": url,
753
+ "summary": summary,
754
+ "markdown_link": f"[{title}]({url})"
755
+ })
756
+ print(f" - {i+1}. {title} ({url})")
757
+ else:
758
+ print("ℹ️ Aucun résultat de recherche web trouvé.")
759
+
760
+ except Exception as e:
761
+ error_msg = f"Erreur lors de la recherche web avec Tavily: {str(e)}"
762
+ print(f"❌ {error_msg}")
763
+ state["errors"].append(error_msg)
764
+
765
+ state["web_search_results"] = web_search_results
766
+ state["messages"].append(AIMessage(content=f"Recherche web terminée avec {len(web_search_results)} résultats."))
767
+
768
+ return state
769
+
770
  # =============================================================================
771
  # FONCTIONS DE ROUTAGE
772
  # =============================================================================
 
823
  workflow.add_node("validate_response", validate_response_node)
824
  workflow.add_node("refine_response", refine_response_node)
825
  workflow.add_node("collect_similar_information", collect_similar_information_node)
826
+ workflow.add_node("web_search", web_search_node) # Ajout du nouveau node de recherche web
827
 
828
  workflow.set_entry_point("analyze_query")
829
 
 
864
  )
865
 
866
  workflow.add_edge("refine_response", "validate_response")
867
+ workflow.add_edge("collect_similar_information", "web_search") # Ajouter un edge vers la recherche web
868
+ workflow.add_edge("web_search", END) # La recherche web est le point final après les infos similaires
869
 
870
  #memory = MemorySaver()
871
  #app = workflow.compile(checkpointer=memory)
 
898
  "final_response": "",
899
  "iteration_count": 0,
900
  "errors": [],
901
+ "additional_information": [],
902
+ "web_search_results": []
903
  }
904
 
905
  print(f"{'='*80}")
 
922
  "iteration_count": final_state.get("iteration_count", 0),
923
  "errors": final_state.get("errors", []),
924
  "additional_information": final_state.get("additional_information", []),
925
+ "web_search_results": final_state.get("web_search_results", []),
926
  "sources_used": [
927
+ info["database"]
928
  for info in final_state.get("collected_information", [])
929
  ],
930
  "pinecone_index": PINECONE_INDEX_NAME
 
1119
  print(result['similar_info_response'])
1120
  print()
1121
 
1122
+ # Nouvelle section : Résultats de la recherche web
1123
+ if result.get('web_search_results') and len(result['web_search_results']) > 0:
1124
+ print(f"\n{'='*80}")
1125
+ print(f"🌐 RÉSULTATS DE LA RECHERCHE WEB (TAVILY)")
1126
+ print(f"{'='*80}")
1127
+ print(f"\nInformations trouvées sur le web via Tavily Search:\n")
1128
+
1129
+ for idx, item in enumerate(result['web_search_results'], 1):
1130
+ print(f" Résultat {idx}:")
1131
+ print(f" ├─ Titre: {item['title']}")
1132
+ print(f" ├─ Lien: {item['markdown_link']}")
1133
+ print(f" └─ Résumé: {item['summary']}\n")
1134
+
1135
  async def main():
1136
  """Fonction principale de l'application."""
1137