commit aaefaedaa3482a9a02c031da181f9655217891f7 Author: Vincent Date: Fri Apr 10 10:15:37 2026 +0000 some langchain llm call diff --git a/.env b/.env new file mode 100644 index 0000000..5932b63 --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +#GOOGLE_API_KEY = "AQ.Ab8RN6KVRupKRqWZACksBWw7MrClcfbyMXGjHPyOFMssOGxFFQ" +GOOGLE_API_KEY = "AIzaSyAmitbNdx29t1uV3XYHdXpC55XCufAPM-g" \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..21d0b89 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.venv/ diff --git a/agent.py b/agent.py new file mode 100644 index 0000000..020aafc --- /dev/null +++ b/agent.py @@ -0,0 +1,49 @@ +import os +from typing import Annotated +from typing_extensions import TypedDict # Plus robuste pour le State + +from dotenv import load_dotenv +from langgraph.graph import StateGraph, START, END +from langgraph.graph.message import add_messages +from langchain_google_vertexai import ChatVertexAI + +load_dotenv() + +# 1. Configuration du modèle (Syntaxe actuelle) +# Assure-hui que GOOGLE_APPLICATION_CREDENTIALS ou GOOGLE_CLOUD_PROJECT est dans ton .env +llm = ChatVertexAI( + model="gemini-1.5-flash", + temperature=0, +) + +# 2. Définition de l'état +# add_messages permet d'accumuler l'historique au lieu de l'écraser +class State(TypedDict): + messages: Annotated[list, add_messages] + +# 3. Le nœud de l'agent +def call_model(state: State): + response = llm.invoke(state["messages"]) + # On retourne un dictionnaire qui sera mergé avec l'état actuel + return {"messages": [response]} + +# 4. Construction du graphe (Architecture actuelle) +builder = StateGraph(State) + +builder.add_node("agent", call_model) + +builder.add_edge(START, "agent") +builder.add_edge("agent", END) + +# Compilation +graph = builder.compile() + +# 5. Exécution propre +if __name__ == "__main__": + initial_state = {"messages": [("user", "Salut, tu tournes sur quelle version de Gemini ?")]} + + # Utilisation de .stream() pour voir ce qui se passe + for chunk in graph.stream(initial_state): + for node, values in chunk.items(): + print(f"--- Node: {node} ---") + print(values["messages"][-1].content) \ No newline at end of file diff --git a/rag_import.py b/rag_import.py new file mode 100644 index 0000000..c34339e --- /dev/null +++ b/rag_import.py @@ -0,0 +1,53 @@ +import os +from dotenv import load_dotenv +#from langchain_community.document_loaders import TextLoader +from langchain_community.document_loaders import Docx2txtLoader +from langchain_text_splitters import RecursiveCharacterTextSplitter +from langchain_google_genai import GoogleGenerativeAIEmbeddings +from langchain_qdrant import QdrantVectorStore + +# 1. Chargement de la clé API +load_dotenv() +api_key = os.getenv("GOOGLE_API_KEY") + +def inserer_documents(): + print("1. Chargement du document...") + # Assurez-vous d'avoir un fichier mon_document.txt à côté de ce script + #loader = TextLoader("resources/cv.docx", encoding="utf-8") + loader = Docx2txtLoader("resources/cv.docx") + documents = loader.load() + + + + + print("2. Découpage du texte en morceaux...") + # On coupe le texte par blocs de 500 caractères, avec un chevauchement de 50 caractères + # (Le chevauchement évite de couper une phrase importante au milieu) + text_splitter = RecursiveCharacterTextSplitter( + chunk_size=500, + chunk_overlap=50 + ) + morceaux = text_splitter.split_documents(documents) + print(f"-> Le document a été découpé en {len(morceaux)} morceau(x).") + + print("3. Connexion au modèle d'Embedding...") + # C'EST CRUCIAL : C'est le même modèle que dans votre script de recherche ! + embeddings = GoogleGenerativeAIEmbeddings(model="models/gemini-embedding-001") + + print("4. Envoi vers Qdrant...") + # On utilise la méthode "from_documents" qui va tout faire d'un coup : + # Créer la collection (si elle n'existe pas), vectoriser, et sauvegarder. + qdrant_url = "http://qdrant:6333" + nom_collection = "rag-1" + + QdrantVectorStore.from_documents( + documents=morceaux, + embedding=embeddings, + url=qdrant_url, + collection_name=nom_collection, + ) + + print("✅ Succès ! Les données sont dans Qdrant.") + +if __name__ == "__main__": + inserer_documents() \ No newline at end of file diff --git a/rag_llm.py b/rag_llm.py new file mode 100644 index 0000000..dfafc36 --- /dev/null +++ b/rag_llm.py @@ -0,0 +1,76 @@ +import os +from dotenv import load_dotenv +from langchain_google_genai import ChatGoogleGenerativeAI, GoogleGenerativeAIEmbeddings +from langchain_qdrant import QdrantVectorStore +from qdrant_client import QdrantClient +from langchain_classic.chains import create_retrieval_chain +from langchain_classic.chains.combine_documents import create_stuff_documents_chain +from langchain_core.prompts import ChatPromptTemplate + +# 1. Chargement de la clé API +load_dotenv() +api_key = os.getenv("GOOGLE_API_KEY") + +def interroger_mon_rag(question): + # --- A. CONFIGURATION DES MODÈLES --- + # Le modèle qui va générer la réponse + llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash", google_api_key=api_key, temperature=0) + + # Le modèle qui transforme le texte en vecteurs (doit être le même que celui utilisé pour remplir la base) + embeddings = GoogleGenerativeAIEmbeddings(model="models/gemini-embedding-001") + + # --- B. CONNEXION À QDRANT --- + # Remplacez l'URL par l'adresse de votre VM (ex: http://localhost:6333) + # Et mettez le vrai nom de votre collection Qdrant + qdrant_url = "http://qdrant:6333" + nom_collection = "rag-1" + + client = QdrantClient(url=qdrant_url) + + # On connecte LangChain à Qdrant + vector_store = QdrantVectorStore( + client=client, + collection_name=nom_collection, + embedding=embeddings + ) + + # On transforme la base en "Retriever" (un outil qui va chercher les 3 meilleurs documents) + retriever = vector_store.as_retriever(search_kwargs={"k": 3}) + + # --- C. CRÉATION DU PROMPT RAG --- + # Le mot {context} sera automatiquement remplacé par les documents trouvés dans Qdrant + system_prompt = ( + "Tu es un assistant utile. Utilise UNIQUEMENT les morceaux de contexte " + "fournis ci-dessous pour répondre à la question. Si tu ne connais pas la réponse " + "à partir du contexte, dis simplement que tu ne sais pas." + "\n\n" + "Contexte :\n{context}" + ) + + prompt = ChatPromptTemplate.from_messages([ + ("system", system_prompt), + ("human", "{input}"), + ]) + + # --- D. ASSEMBLAGE DE LA CHAÎNE --- + # 1. Chaîne qui combine les documents récupérés et le prompt + question_answer_chain = create_stuff_documents_chain(llm, prompt) + + # 2. Chaîne globale qui fait la recherche PUIS appelle la chaîne précédente + rag_chain = create_retrieval_chain(retriever, question_answer_chain) + + # --- E. EXÉCUTION --- + print(f"Recherche de la réponse pour : '{question}'...\n") + reponse = rag_chain.invoke({"input": question}) + + print("🤖 Réponse de Gemini :") + print(reponse["answer"]) + + print("\n📄 Documents sources utilisés :") + for doc in reponse["context"]: + # Affiche un extrait du document source et ses métadonnées + print(f"- {doc.page_content[:100]}... (Source: {doc.metadata})") + +# Test du script +if __name__ == "__main__": + interroger_mon_rag("Quelles sont les passions de vincent poupet ?") \ No newline at end of file diff --git a/requirements b/requirements new file mode 100644 index 0000000..6925f61 --- /dev/null +++ b/requirements @@ -0,0 +1,12 @@ +langchain +langchain_classic +langchain_community +langgraph +langchain-google-vertexai +langchain-core +langchain-google-genai +dotenv +qdrant-client +langchain-qdrant +langchain-chain +docx2txt \ No newline at end of file diff --git a/resources/cv.docx b/resources/cv.docx new file mode 100644 index 0000000..6306165 Binary files /dev/null and b/resources/cv.docx differ diff --git a/simple_llm_call.py b/simple_llm_call.py new file mode 100644 index 0000000..f1d1869 --- /dev/null +++ b/simple_llm_call.py @@ -0,0 +1,30 @@ +import os +from dotenv import load_dotenv +from langchain_google_genai import ChatGoogleGenerativeAI + + +# Charger les variables du fichier .env +load_dotenv() +api_key = os.getenv("GOOGLE_API_KEY") + +# 1. Configuration de la clé API +# Remplacez 'VOTRE_CLE_API' par votre véritable clé +#os.environ["GOOGLE_API_KEY"] = api_key + +def interroger_gemini(question): + # 2. Initialisation du modèle + # On choisit le modèle 'gemini-1.5-flash' pour sa rapidité + llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash",google_api_key=api_key) + + # 3. Appel du modèle + print(f"Question posée : {question}") + reponse = llm.invoke(question) + + # Affichage du contenu de la réponse + return reponse.content + +# Test du script +if __name__ == "__main__": + resultat = interroger_gemini("Quels sont les 3 avantages d'apprendre Python ?") + print("\nRéponse de Gemini :") + print(resultat) \ No newline at end of file diff --git a/system_llm_call.py b/system_llm_call.py new file mode 100644 index 0000000..0ee7626 --- /dev/null +++ b/system_llm_call.py @@ -0,0 +1,29 @@ +import os +from dotenv import load_dotenv +from langchain_google_genai import ChatGoogleGenerativeAI +from langchain_core.prompts import ChatPromptTemplate + +# Charger les variables du fichier .env +load_dotenv() +api_key = os.getenv("GOOGLE_API_KEY") + +# Initialisation du modèle +llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash",google_api_key=api_key) + +def expert_en_codage(concept): + # 1. On définit un Template (le "moule" de la question) + prompt = ChatPromptTemplate.from_messages([ + ("system", "Tu es un expert en programmation Python. Explique les concepts de manière simple avec un exemple de code court."), + ("human", "Explique-moi le concept suivant : {concept}") + ]) + + # 2. On crée une "chaîne" (Chain) simple + chain = prompt | llm + + # 3. On lance la chaîne en remplissant la variable + reponse = chain.invoke({"concept": concept}) + + print(reponse.content) + +# Test +expert_en_codage("Les list comprehensions") \ No newline at end of file diff --git a/system_llm_stream.py b/system_llm_stream.py new file mode 100644 index 0000000..fc281a3 --- /dev/null +++ b/system_llm_stream.py @@ -0,0 +1,31 @@ +import os +from dotenv import load_dotenv +from langchain_google_genai import ChatGoogleGenerativeAI +from langchain_core.prompts import ChatPromptTemplate + +# Charger les variables du fichier .env +load_dotenv() +api_key = os.getenv("GOOGLE_API_KEY") + +# Initialisation du modèle +llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash",google_api_key=api_key) + +def expert_en_codage(concept): + # 1. On définit un Template (le "moule" de la question) + prompt = ChatPromptTemplate.from_messages([ + ("system", "Tu es un expert en programmation Python. Explique les concepts de manière simple avec un exemple de code court."), + ("human", "Explique-moi le concept suivant : {concept}") + ]) + + # 2. On crée une "chaîne" (Chain) simple + chain = prompt | llm + + # Au lieu de .invoke(), on utilise .stream() + # Cela retourne un générateur (itérable) + for chunk in chain.stream({"concept": concept}): + # Chaque 'chunk' est un morceau de la réponse + # On utilise end="" pour ne pas revenir à la ligne et flush=True pour forcer l'affichage + print(chunk.content, end="", flush=True) + +# Test +expert_en_codage("Les variables") \ No newline at end of file diff --git a/test.py b/test.py new file mode 100644 index 0000000..75483a3 --- /dev/null +++ b/test.py @@ -0,0 +1,2 @@ +import sys +print("🔍 Le Python qui s'exécute actuellement est :", sys.executable) \ No newline at end of file