Ana2012 commited on
Commit
335205d
·
verified ·
1 Parent(s): e9058d2

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +239 -238
main.py CHANGED
@@ -1,238 +1,239 @@
1
- import os
2
- import threading
3
- from pathlib import Path
4
- from typing import Optional
5
-
6
- from fastapi import FastAPI, Query, Response
7
- from fastapi.middleware.cors import CORSMiddleware
8
- from fastapi.responses import FileResponse, HTMLResponse, RedirectResponse
9
- from pydantic import BaseModel
10
-
11
- from .agent import ShoppingAgent
12
- from .feedback import caminho_feedback, google_sheets_habilitado, salvar_feedback
13
- from .google_oauth import build_flow, get_authorization_url, load_credentials, save_credentials
14
- from .logger import salvar_log_busca
15
- from .memory import caminho_memoria_negativa
16
-
17
- EMBEDDING_PROVIDER = os.getenv("EMBEDDING_PROVIDER", "transformers").strip().lower()
18
- HF_MODEL_REPO = os.getenv("HF_MODEL_REPO", "Ana2012/bertimbau-buscador").strip()
19
-
20
-
21
- def _env_flag(name, default="true"):
22
- return os.getenv(name, default).strip().lower() in {"1", "true", "yes", "on"}
23
-
24
-
25
- PRELOAD_AGENT = _env_flag("PRELOAD_AGENT", "true")
26
- LOGS_DIR = os.getenv("LOGS_DIR", "/data/logs")
27
- DATA_DIR = "/data"
28
-
29
- app = FastAPI(title="TCC2 Agent API")
30
-
31
- app.add_middleware(
32
- CORSMiddleware,
33
- allow_origins=["*"],
34
- allow_credentials=False,
35
- allow_methods=["*"],
36
- allow_headers=["*"],
37
- )
38
-
39
- agent = None
40
- agent_lock = threading.Lock()
41
-
42
-
43
- def get_agent():
44
- global agent
45
- if agent is None:
46
- with agent_lock:
47
- if agent is None:
48
- agent = ShoppingAgent()
49
- return agent
50
-
51
-
52
- @app.on_event("startup")
53
- def preload_agent():
54
- if PRELOAD_AGENT:
55
- get_agent()
56
-
57
-
58
- class ChatRequest(BaseModel):
59
- query: Optional[str] = None
60
- message: Optional[str] = None
61
- top_k: int = 5
62
-
63
-
64
- class FeedbackRequest(BaseModel):
65
- query: str
66
- product_id: str
67
- product_name: str
68
- rating: Optional[int] = None
69
- is_helpful: Optional[bool] = None
70
- note: Optional[str] = None
71
- categoria_inferida: Optional[str] = None
72
- feedback: Optional[str] = None
73
- motivo: Optional[str] = None
74
- score_final: Optional[float] = None
75
- score_semantico: Optional[float] = None
76
- bonus_lexical: Optional[float] = None
77
- penalidade_feedback: Optional[float] = None
78
- user_message: Optional[str] = None
79
-
80
-
81
- @app.get("/health")
82
- def health():
83
- runtime = get_agent().runtime_info() if agent is not None else None
84
- return {
85
- "status": "ok",
86
- "agent_ready": agent is not None,
87
- "embedding_provider": EMBEDDING_PROVIDER,
88
- "model_repo": HF_MODEL_REPO,
89
- "preload_agent": PRELOAD_AGENT,
90
- "runtime": runtime,
91
- "feedback_storage": "google_sheets" if google_sheets_habilitado() else "csv",
92
- }
93
-
94
-
95
- @app.get("/", include_in_schema=False)
96
- def root():
97
- return RedirectResponse(url="/docs")
98
-
99
-
100
- @app.get("/favicon.ico", include_in_schema=False)
101
- def favicon():
102
- return Response(status_code=204)
103
-
104
-
105
- @app.get("/auth/google")
106
- def auth_google():
107
- authorization_url, _state = get_authorization_url()
108
- return RedirectResponse(url=authorization_url)
109
-
110
-
111
- @app.get("/oauth2callback")
112
- def oauth2callback(code: str = Query(...)):
113
- flow = build_flow()
114
- flow.fetch_token(code=code)
115
- save_credentials(flow.credentials)
116
- return HTMLResponse(
117
- "<h3>Autorizacao concluida. O backend ja pode salvar feedbacks no Google Sheets.</h3>"
118
- )
119
-
120
-
121
- @app.get("/auth/status")
122
- def auth_status():
123
- credentials = load_credentials()
124
- connected = credentials is not None and credentials.valid
125
- return {
126
- "google_sheets_connected": connected,
127
- "message": (
128
- "Google Sheets autorizado e pronto para uso."
129
- if connected
130
- else "Google Sheets ainda nao autorizado. Acesse /auth/google para conectar."
131
- ),
132
- }
133
-
134
-
135
- @app.get("/debug/files")
136
- def debug_files():
137
- data_path = Path(DATA_DIR)
138
- logs_path = Path(LOGS_DIR)
139
- feedback_path = Path(caminho_feedback())
140
- memory_path = Path(caminho_memoria_negativa())
141
-
142
- return {
143
- "data_exists": data_path.exists(),
144
- "logs_exists": logs_path.exists(),
145
- "feedback_exists": feedback_path.exists(),
146
- "negative_memory_exists": memory_path.exists(),
147
- "data_files": sorted(p.name for p in data_path.iterdir()) if data_path.exists() else [],
148
- "logs_files": sorted(p.name for p in logs_path.iterdir()) if logs_path.exists() else [],
149
- "feedback_file": str(feedback_path),
150
- "negative_memory_file": str(memory_path),
151
- "feedback_storage": "google_sheets" if google_sheets_habilitado() else "csv",
152
- }
153
-
154
-
155
- @app.get("/debug/feedback")
156
- def debug_feedback():
157
- feedback_path = Path(caminho_feedback())
158
- if not feedback_path.exists():
159
- return {"error": "arquivo nao existe"}
160
-
161
- return {"conteudo": feedback_path.read_text(encoding="utf-8")}
162
-
163
-
164
- @app.get("/download/feedback")
165
- def download_feedback():
166
- feedback_path = caminho_feedback()
167
- if not os.path.exists(feedback_path):
168
- return {"error": "arquivo nao existe"}
169
-
170
- return FileResponse(feedback_path, filename="feedback.csv")
171
-
172
-
173
- @app.get("/debug/memory")
174
- def debug_memory():
175
- memory_path = Path(caminho_memoria_negativa())
176
- if not memory_path.exists():
177
- return {"status": "missing", "file": str(memory_path)}
178
-
179
- return {
180
- "status": "ok",
181
- "file": str(memory_path),
182
- "content": memory_path.read_text(encoding="utf-8"),
183
- }
184
-
185
-
186
- @app.post("/chat")
187
- def chat(request: ChatRequest):
188
- texto = request.query or request.message
189
-
190
- if not texto:
191
- return {"error": "query ou message deve ser informado"}
192
-
193
- resultado = get_agent().responder(texto, top_k=request.top_k)
194
- salvar_log_busca(resultado)
195
- return resultado
196
-
197
-
198
- @app.post("/feedback")
199
- def feedback(request: FeedbackRequest):
200
- feedback_file = caminho_feedback()
201
- print(
202
- "Salvando feedback:",
203
- {
204
- "query": request.query,
205
- "product_id": request.product_id,
206
- "feedback_file": feedback_file,
207
- "logs_dir_exists": os.path.exists(LOGS_DIR),
208
- "google_sheets_enabled": google_sheets_habilitado(),
209
- },
210
- )
211
-
212
- try:
213
- return salvar_feedback(
214
- query=request.query,
215
- product_id=request.product_id,
216
- product_name=request.product_name,
217
- rating=request.rating,
218
- is_helpful=request.is_helpful,
219
- note=request.note,
220
- categoria_inferida=request.categoria_inferida,
221
- feedback=request.feedback,
222
- motivo=request.motivo,
223
- score_final=request.score_final,
224
- score_semantico=request.score_semantico,
225
- bonus_lexical=request.bonus_lexical,
226
- penalidade_feedback=request.penalidade_feedback,
227
- user_message=request.user_message,
228
- )
229
- except Exception as exc:
230
- return {
231
- "ok": False,
232
- "saved_local": False,
233
- "saved_google_sheets": False,
234
- "detail": str(exc),
235
- "feedback_file": feedback_file,
236
- "logs_dir_exists": os.path.exists(LOGS_DIR),
237
- "google_sheets_enabled": google_sheets_habilitado(),
238
- }
 
 
1
+ import os
2
+ import threading
3
+ from pathlib import Path
4
+ from typing import Optional
5
+ from fastapi import FastAPI, Request
6
+
7
+ from fastapi import FastAPI, Query, Response
8
+ from fastapi.middleware.cors import CORSMiddleware
9
+ from fastapi.responses import FileResponse, HTMLResponse, RedirectResponse
10
+ from pydantic import BaseModel
11
+
12
+ from .agent import ShoppingAgent
13
+ from .feedback import caminho_feedback, google_sheets_habilitado, salvar_feedback
14
+ from .google_oauth import build_flow, get_authorization_url, load_credentials, save_credentials
15
+ from .logger import salvar_log_busca
16
+ from .memory import caminho_memoria_negativa
17
+
18
+ EMBEDDING_PROVIDER = os.getenv("EMBEDDING_PROVIDER", "transformers").strip().lower()
19
+ HF_MODEL_REPO = os.getenv("HF_MODEL_REPO", "Ana2012/bertimbau-buscador").strip()
20
+
21
+
22
+ def _env_flag(name, default="true"):
23
+ return os.getenv(name, default).strip().lower() in {"1", "true", "yes", "on"}
24
+
25
+
26
+ PRELOAD_AGENT = _env_flag("PRELOAD_AGENT", "true")
27
+ LOGS_DIR = os.getenv("LOGS_DIR", "/data/logs")
28
+ DATA_DIR = "/data"
29
+
30
+ app = FastAPI(title="TCC2 Agent API")
31
+
32
+ app.add_middleware(
33
+ CORSMiddleware,
34
+ allow_origins=["*"],
35
+ allow_credentials=False,
36
+ allow_methods=["*"],
37
+ allow_headers=["*"],
38
+ )
39
+
40
+ agent = None
41
+ agent_lock = threading.Lock()
42
+
43
+
44
+ def get_agent():
45
+ global agent
46
+ if agent is None:
47
+ with agent_lock:
48
+ if agent is None:
49
+ agent = ShoppingAgent()
50
+ return agent
51
+
52
+
53
+ @app.on_event("startup")
54
+ def preload_agent():
55
+ if PRELOAD_AGENT:
56
+ get_agent()
57
+
58
+
59
+ class ChatRequest(BaseModel):
60
+ query: Optional[str] = None
61
+ message: Optional[str] = None
62
+ top_k: int = 5
63
+
64
+
65
+ class FeedbackRequest(BaseModel):
66
+ query: str
67
+ product_id: str
68
+ product_name: str
69
+ rating: Optional[int] = None
70
+ is_helpful: Optional[bool] = None
71
+ note: Optional[str] = None
72
+ categoria_inferida: Optional[str] = None
73
+ feedback: Optional[str] = None
74
+ motivo: Optional[str] = None
75
+ score_final: Optional[float] = None
76
+ score_semantico: Optional[float] = None
77
+ bonus_lexical: Optional[float] = None
78
+ penalidade_feedback: Optional[float] = None
79
+ user_message: Optional[str] = None
80
+
81
+
82
+ @app.get("/health")
83
+ def health():
84
+ runtime = get_agent().runtime_info() if agent is not None else None
85
+ return {
86
+ "status": "ok",
87
+ "agent_ready": agent is not None,
88
+ "embedding_provider": EMBEDDING_PROVIDER,
89
+ "model_repo": HF_MODEL_REPO,
90
+ "preload_agent": PRELOAD_AGENT,
91
+ "runtime": runtime,
92
+ "feedback_storage": "google_sheets" if google_sheets_habilitado() else "csv",
93
+ }
94
+
95
+
96
+ @app.get("/", include_in_schema=False)
97
+ def root():
98
+ return RedirectResponse(url="/docs")
99
+
100
+
101
+ @app.get("/favicon.ico", include_in_schema=False)
102
+ def favicon():
103
+ return Response(status_code=204)
104
+
105
+
106
+ @app.get("/auth/google")
107
+ def auth_google():
108
+ authorization_url, _state = get_authorization_url()
109
+ return RedirectResponse(url=authorization_url)
110
+
111
+
112
+ @app.get("/oauth2callback")
113
+ def oauth2callback(code: str = Query(...)):
114
+ flow = build_flow()
115
+ flow.fetch_token(code=code)
116
+ save_credentials(flow.credentials)
117
+ return HTMLResponse(
118
+ "<h3>Autorizacao concluida. O backend ja pode salvar feedbacks no Google Sheets.</h3>"
119
+ )
120
+
121
+
122
+ @app.get("/auth/status")
123
+ def auth_status():
124
+ credentials = load_credentials()
125
+ connected = credentials is not None and credentials.valid
126
+ return {
127
+ "google_sheets_connected": connected,
128
+ "message": (
129
+ "Google Sheets autorizado e pronto para uso."
130
+ if connected
131
+ else "Google Sheets ainda nao autorizado. Acesse /auth/google para conectar."
132
+ ),
133
+ }
134
+
135
+
136
+ @app.get("/debug/files")
137
+ def debug_files():
138
+ data_path = Path(DATA_DIR)
139
+ logs_path = Path(LOGS_DIR)
140
+ feedback_path = Path(caminho_feedback())
141
+ memory_path = Path(caminho_memoria_negativa())
142
+
143
+ return {
144
+ "data_exists": data_path.exists(),
145
+ "logs_exists": logs_path.exists(),
146
+ "feedback_exists": feedback_path.exists(),
147
+ "negative_memory_exists": memory_path.exists(),
148
+ "data_files": sorted(p.name for p in data_path.iterdir()) if data_path.exists() else [],
149
+ "logs_files": sorted(p.name for p in logs_path.iterdir()) if logs_path.exists() else [],
150
+ "feedback_file": str(feedback_path),
151
+ "negative_memory_file": str(memory_path),
152
+ "feedback_storage": "google_sheets" if google_sheets_habilitado() else "csv",
153
+ }
154
+
155
+
156
+ @app.get("/debug/feedback")
157
+ def debug_feedback():
158
+ feedback_path = Path(caminho_feedback())
159
+ if not feedback_path.exists():
160
+ return {"error": "arquivo nao existe"}
161
+
162
+ return {"conteudo": feedback_path.read_text(encoding="utf-8")}
163
+
164
+
165
+ @app.get("/download/feedback")
166
+ def download_feedback():
167
+ feedback_path = caminho_feedback()
168
+ if not os.path.exists(feedback_path):
169
+ return {"error": "arquivo nao existe"}
170
+
171
+ return FileResponse(feedback_path, filename="feedback.csv")
172
+
173
+
174
+ @app.get("/debug/memory")
175
+ def debug_memory():
176
+ memory_path = Path(caminho_memoria_negativa())
177
+ if not memory_path.exists():
178
+ return {"status": "missing", "file": str(memory_path)}
179
+
180
+ return {
181
+ "status": "ok",
182
+ "file": str(memory_path),
183
+ "content": memory_path.read_text(encoding="utf-8"),
184
+ }
185
+
186
+
187
+ @app.post("/chat")
188
+ def chat(request: ChatRequest):
189
+ texto = request.query or request.message
190
+
191
+ if not texto:
192
+ return {"error": "query ou message deve ser informado"}
193
+
194
+ resultado = get_agent().responder(texto, top_k=request.top_k)
195
+ salvar_log_busca(resultado)
196
+ return resultado
197
+
198
+
199
+ @app.post("/feedback")
200
+ def feedback(request: FeedbackRequest):
201
+ feedback_file = caminho_feedback()
202
+ print(
203
+ "Salvando feedback:",
204
+ {
205
+ "query": request.query,
206
+ "product_id": request.product_id,
207
+ "feedback_file": feedback_file,
208
+ "logs_dir_exists": os.path.exists(LOGS_DIR),
209
+ "google_sheets_enabled": google_sheets_habilitado(),
210
+ },
211
+ )
212
+
213
+ try:
214
+ return salvar_feedback(
215
+ query=request.query,
216
+ product_id=request.product_id,
217
+ product_name=request.product_name,
218
+ rating=request.rating,
219
+ is_helpful=request.is_helpful,
220
+ note=request.note,
221
+ categoria_inferida=request.categoria_inferida,
222
+ feedback=request.feedback,
223
+ motivo=request.motivo,
224
+ score_final=request.score_final,
225
+ score_semantico=request.score_semantico,
226
+ bonus_lexical=request.bonus_lexical,
227
+ penalidade_feedback=request.penalidade_feedback,
228
+ user_message=request.user_message,
229
+ )
230
+ except Exception as exc:
231
+ return {
232
+ "ok": False,
233
+ "saved_local": False,
234
+ "saved_google_sheets": False,
235
+ "detail": str(exc),
236
+ "feedback_file": feedback_file,
237
+ "logs_dir_exists": os.path.exists(LOGS_DIR),
238
+ "google_sheets_enabled": google_sheets_habilitado(),
239
+ }