dav74 commited on
Commit
8ddbeb8
·
verified ·
1 Parent(s): 0aca396

Upload main.py

Browse files
Files changed (1) hide show
  1. main.py +145 -0
main.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain_core.prompts import ChatPromptTemplate
2
+ from langchain_google_genai import ChatGoogleGenerativeAI
3
+ from langchain_community.document_loaders import DirectoryLoader
4
+ from langchain_text_splitters import CharacterTextSplitter
5
+ from langchain_community.document_loaders import PyPDFLoader
6
+ from langchain_huggingface import HuggingFaceEmbeddings
7
+ from typing import List
8
+ from langchain_chroma import Chroma
9
+ from typing_extensions import TypedDict
10
+ from typing import Annotated
11
+ from langgraph.graph.message import AnyMessage, add_messages
12
+ from langchain_core.messages import HumanMessage, AIMessage
13
+ from langgraph.graph import END, StateGraph, START
14
+ from langgraph.checkpoint.memory import MemorySaver
15
+ from fastapi import FastAPI, UploadFile, Form
16
+ from fastapi.middleware.cors import CORSMiddleware
17
+ from typing import Optional
18
+ from PIL import Image
19
+ import base64
20
+ from io import BytesIO
21
+ import os
22
+ import logging
23
+ import sys
24
+
25
+ logger = logging.getLogger('uvicorn.error')
26
+ logger.setLevel(logging.DEBUG)
27
+
28
+ app = FastAPI()
29
+
30
+ app.add_middleware(
31
+ CORSMiddleware,
32
+ allow_origins=["*"],
33
+ allow_credentials=True,
34
+ allow_methods=["*"],
35
+ allow_headers=["*"],
36
+ )
37
+
38
+ QOOGLE_API = "AIzaSyByFsTIeE6ifzSsAl__cqGGWZ20JXznsJE"
39
+
40
+ llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash", temperature=0.5, api_key = QOOGLE_API)
41
+
42
+ memory = MemorySaver()
43
+
44
+ glob_pattern="./*.md"
45
+ directory_path = "./documents"
46
+ loader = DirectoryLoader(directory_path, glob=glob_pattern)
47
+ doc_2025 = loader.load()
48
+
49
+ file_path_prob = "./documents/prob.pdf"
50
+ loader_prob = PyPDFLoader(file_path_prob)
51
+ prob = loader_prob.load()
52
+
53
+ file_path_guide = "./documents/prob.pdf"
54
+ loader_guide = PyPDFLoader(file_path_guide)
55
+ guide = loader_guide.load()
56
+
57
+ file_path_QR = "./documents/prob.pdf"
58
+ loader_QR = PyPDFLoader(file_path_QR)
59
+ QR = loader_QR.load()
60
+
61
+ system = """
62
+ Tu es un assistant expert en pédagogie. Ta spécialité est le **grand oral** (épreuve du bacalauréat technique et général).
63
+ Ton interlocuteur est un élève qui est en train de préparer son épreuve de grand oral.
64
+ Ton rôle est d'aider l'élève à préparer son grand oral
65
+ Tu dois répondre à toutes ses questions : organisation de l'épreuve, but de l'épreuve...
66
+ Tu dois aussi l'aider à trouver un sujet et à construire sa problématique.
67
+ Tu dois uniquement discuter du grand oral avec ton interlocuteur
68
+ Si tu ne connais pas la réponse à une question, propose à l'élève de demander à son professeur.
69
+ """
70
+
71
+ prompt = ChatPromptTemplate.from_messages(
72
+ [
73
+ ("system", system),
74
+ ("human", """
75
+ Voici différents documents qui t'aideront à répondre aux questions des élèves :
76
+ Le guide du grand oral :
77
+ {guide}
78
+ Un ensemble de Question-Réponse sur le Grand Oral:
79
+ {QR}
80
+ Un texte qui explique la notion de sujet et de problématique:
81
+ {prob}
82
+ Les informations à jour sur le déroulement de l'épreuve (si tu trouves des informations qui te semble contradictoires dans les documents ci-dessous, c'est le documents ci-dessous qui doit être ta source d'informations) :
83
+ {doc_2025}
84
+ Tu trouveras aussi l'historique conversation avec l'élève : \n {historical}
85
+ Et enfin l'intervention de l'élève : {question}"),
86
+ """)
87
+ ]
88
+ )
89
+
90
+ def format_historical(hist):
91
+ historical = []
92
+ for i in range(0,len(hist)-2,2):
93
+ historical.append("Utilisateur : "+hist[i].content[0]['text'])
94
+ historical.append("Assistant : "+hist[i+1].content[0]['text'])
95
+ return "\n".join(historical[-20:])
96
+
97
+
98
+ class GraphState(TypedDict):
99
+ messages: Annotated[list[AnyMessage], add_messages]
100
+
101
+ def chatbot(state : GraphState):
102
+ question = prompt.invoke({'historical': format_historical(state['messages']),'prob':prob, 'doc_2025':doc_2025, 'guide':guide, 'QR':QR , 'question' : state['messages'][-1].content[0]['text']})
103
+ q = question.messages[0].content + question.messages[1].content
104
+ if len(state['messages'][-1].content) > 1 :
105
+ response = llm.invoke([HumanMessage(
106
+ content=[
107
+ {"type": "text", "text": q},
108
+ state['messages'][-1].content[1]
109
+ ])])
110
+ else :
111
+ response = llm.invoke([HumanMessage(
112
+ content=[
113
+ {"type": "text", "text": q}
114
+ ])])
115
+ return {"messages": [AIMessage(content=[{'type': 'text', 'text': response.content}])]}
116
+
117
+ workflow = StateGraph(GraphState)
118
+ workflow.add_node('chatbot', chatbot)
119
+
120
+ workflow.add_edge(START, 'chatbot')
121
+ workflow.add_edge('chatbot', END)
122
+
123
+ app_chatbot = workflow.compile(checkpointer=memory)
124
+
125
+ @app.post('/request')
126
+ def request(id:Annotated[str, Form()], query:Annotated[str, Form()], image:Optional[UploadFile] = None):
127
+ config = {"configurable": {"thread_id": id}}
128
+ if image:
129
+ try:
130
+ img = Image.open(image.file)
131
+ img_buffer = BytesIO()
132
+ img.save(img_buffer, format='PNG')
133
+ byte_data = img_buffer.getvalue()
134
+ base64_img = base64.b64encode(byte_data).decode("utf-8")
135
+ message = HumanMessage(
136
+ content=[
137
+ {'type': 'text', 'text': query},
138
+ {'type': 'image_url', 'image_url': {"url": f"data:image/jpeg;base64,{base64_img}"}}
139
+ ])
140
+ except:
141
+ return {"response":"Attention, vous m'avez fourni autre chose qu'une image. Renouvelez votre demande avec une image."}
142
+ rep = app_chatbot.invoke({"messages": message},config, stream_mode="values")
143
+ else :
144
+ rep = app_chatbot.invoke({"messages": [HumanMessage(content=[{'type': 'text', 'text': query}])]},config, stream_mode="values")
145
+ return {"response":rep['messages'][-1].content[0]['text']}