thibautmodrin commited on
Commit
01ea0bb
·
1 Parent(s): 2af896e

fast_api_chat

Browse files
Files changed (5) hide show
  1. .env +10 -0
  2. Dockerfile +25 -0
  3. __pycache__/main.cpython-312.pyc +0 -0
  4. main.py +162 -0
  5. requirements.txt +10 -0
.env ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ # Configuration Weaviate
2
+ WEAVIATE_URL=http://127.0.0.1:8080
3
+ WEAVIATE_PORT=50051
4
+
5
+ # Configuration OpenAI
6
+ OPENAI_API_KEY=your-openai-api-key
7
+
8
+ # Configuration de l'API
9
+ API_HOST=0.0.0.0
10
+ API_PORT=8000
Dockerfile ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Utilisation d'une image Python officielle
2
+ FROM python:3.10-slim
3
+
4
+ # Définition du répertoire de travail
5
+ WORKDIR /app
6
+
7
+ # Installation des dépendances système
8
+ RUN apt-get update && apt-get install -y \
9
+ build-essential \
10
+ && rm -rf /var/lib/apt/lists/*
11
+
12
+ # Copie des fichiers de dépendances
13
+ COPY requirements.txt .
14
+
15
+ # Installation des dépendances Python
16
+ RUN pip install --no-cache-dir -r requirements.txt
17
+
18
+ # Copie du code source
19
+ COPY . .
20
+
21
+ # Exposition du port
22
+ EXPOSE 8000
23
+
24
+ # Commande de démarrage
25
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
__pycache__/main.cpython-312.pyc ADDED
Binary file (6.55 kB). View file
 
main.py ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from pydantic import BaseModel
4
+ from typing import List, Optional
5
+ import os
6
+ from weaviate.connect import ConnectionParams
7
+ from weaviate import WeaviateClient
8
+ from langchain_huggingface import HuggingFaceEmbeddings
9
+ from langchain_weaviate import WeaviateVectorStore
10
+ from langchain_openai import ChatOpenAI
11
+ from langchain.chains.conversational_retrieval.base import ConversationalRetrievalChain
12
+ from langchain.memory import ConversationBufferMemory
13
+ from langchain.prompts import PromptTemplate
14
+ import time
15
+ from threading import Lock
16
+
17
+ app = FastAPI(
18
+ title="Vitizen Chat API",
19
+ description="API pour le chat RAG avec Weaviate",
20
+ version="1.0.0"
21
+ )
22
+
23
+ # Configuration CORS
24
+ app.add_middleware(
25
+ CORSMiddleware,
26
+ allow_origins=["*"],
27
+ allow_credentials=True,
28
+ allow_methods=["*"],
29
+ allow_headers=["*"],
30
+ )
31
+
32
+ # Configuration du rate limiting
33
+ RATE_LIMIT = 3
34
+ RATE_WINDOW = 1
35
+ last_request_time = 0
36
+ request_lock = Lock()
37
+
38
+ def wait_for_rate_limit():
39
+ global last_request_time
40
+ with request_lock:
41
+ current_time = time.time()
42
+ time_since_last_request = current_time - last_request_time
43
+ if time_since_last_request < RATE_WINDOW / RATE_LIMIT:
44
+ sleep_time = (RATE_WINDOW / RATE_LIMIT) - time_since_last_request
45
+ time.sleep(sleep_time)
46
+ last_request_time = time.time()
47
+
48
+ class RateLimitedChatOpenAI(ChatOpenAI):
49
+ def _call(self, *args, **kwargs):
50
+ wait_for_rate_limit()
51
+ return super()._call(*args, **kwargs)
52
+
53
+ # Modèles Pydantic
54
+ class ChatRequest(BaseModel):
55
+ question: str
56
+ history: Optional[List[dict]] = []
57
+
58
+ class ChatResponse(BaseModel):
59
+ answer: str
60
+
61
+ # Configuration Weaviate
62
+ def setup_weaviate():
63
+ client = WeaviateClient(
64
+ connection_params=ConnectionParams.from_url(
65
+ os.getenv("WEAVIATE_URL", "http://127.0.0.1:8080"),
66
+ int(os.getenv("WEAVIATE_PORT", "50051"))
67
+ )
68
+ )
69
+ client.connect()
70
+ return client
71
+
72
+ # Configuration du RAG
73
+ def setup_rag_chain():
74
+ client = setup_weaviate()
75
+
76
+ embeddings = HuggingFaceEmbeddings(
77
+ model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2",
78
+ model_kwargs={'device': 'cpu'},
79
+ encode_kwargs={'normalize_embeddings': True}
80
+ )
81
+
82
+ vectorstore = WeaviateVectorStore(
83
+ client=client,
84
+ embedding=embeddings,
85
+ index_name="Document",
86
+ text_key="text"
87
+ )
88
+
89
+ llm = RateLimitedChatOpenAI(
90
+ openai_api_key=os.getenv("OPENAI_API_KEY"),
91
+ model_name="gpt-4-turbo-preview",
92
+ temperature=0,
93
+ streaming=True
94
+ )
95
+
96
+ memory = ConversationBufferMemory(
97
+ memory_key="chat_history",
98
+ return_messages=True,
99
+ output_key="answer"
100
+ )
101
+
102
+ retriever = vectorstore.as_retriever(
103
+ search_type="similarity",
104
+ search_kwargs={"k": 30}
105
+ )
106
+
107
+ # Création du prompt personnalisé
108
+ prompt = PromptTemplate(
109
+ template="""Tu es un assistant expert en pulvérisation viticole et produits phytosanitaires.
110
+ Tu as une expertise approfondie dans :
111
+ - Les différents types de pulvérisateurs et leurs caractéristiques techniques
112
+ - Les produits phytosanitaires et leurs utilisations
113
+ - Les bonnes pratiques de pulvérisation
114
+ - La réglementation en matière de phytosanitaires
115
+ - La protection de l'environnement et la sécurité
116
+
117
+ Utilise les informations suivantes pour répondre à la question de l'utilisateur.
118
+ Si tu ne connais pas la réponse, dis-le simplement. N'invente pas d'informations.
119
+
120
+ Contexte:
121
+ {context}
122
+
123
+ Question: {question}
124
+
125
+ Réponse:""",
126
+ input_variables=["context", "question"]
127
+ )
128
+
129
+ return ConversationalRetrievalChain.from_llm(
130
+ llm=llm,
131
+ retriever=retriever,
132
+ memory=memory,
133
+ combine_docs_chain_kwargs={"prompt": prompt},
134
+ return_source_documents=True,
135
+ return_generated_question=True,
136
+ output_key="answer"
137
+ )
138
+
139
+ # Initialisation du RAG
140
+ qa_chain = setup_rag_chain()
141
+
142
+ @app.post("/chat", response_model=ChatResponse)
143
+ async def chat(request: ChatRequest):
144
+ try:
145
+ response = qa_chain.invoke({
146
+ "question": request.question,
147
+ "chat_history": request.history
148
+ })
149
+
150
+ return ChatResponse(
151
+ answer=response["answer"]
152
+ )
153
+ except Exception as e:
154
+ raise HTTPException(status_code=500, detail=str(e))
155
+
156
+ @app.get("/health")
157
+ async def health_check():
158
+ return {"status": "healthy"}
159
+
160
+ if __name__ == "__main__":
161
+ import uvicorn
162
+ uvicorn.run(app, host="0.0.0.0", port=8000)
requirements.txt ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ fastapi==0.104.1
2
+ uvicorn==0.24.0
3
+ pydantic==2.4.2
4
+ weaviate-client==3.24.1
5
+ langchain==0.0.335
6
+ langchain-openai==0.0.2
7
+ langchain-huggingface==0.0.5
8
+ langchain-weaviate==0.0.1
9
+ sentence-transformers==2.2.2
10
+ python-dotenv==1.0.0