From 61e81f01fedf77e094bea15ff8958746ebc33fee Mon Sep 17 00:00:00 2001 From: fredsimon Date: Mon, 13 Apr 2026 20:11:17 +0000 Subject: [PATCH] init --- Dockerfile | 7 ++++ main.py | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 5 +++ 3 files changed, 100 insertions(+) create mode 100644 Dockerfile create mode 100644 main.py create mode 100644 requirements.txt diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..fef8636 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.12-slim +WORKDIR /app +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt +COPY main.py . +EXPOSE 3000 +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "3000"] \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..5ac4f19 --- /dev/null +++ b/main.py @@ -0,0 +1,88 @@ +from fastapi import FastAPI, HTTPException +from fastapi.middleware.cors import CORSMiddleware +from pydantic import BaseModel +from datetime import datetime +import platform +import urllib.request +import json as jsonlib + +app = FastAPI(title="PropFirms API", version="1.2.0") + +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_methods=["*"], + allow_headers=["*"], +) + +OLLAMA_URL = "http://10.0.1.1:11435" + +SYSTEM_PROMPT = """Tu es un assistant spécialisé dans le trading et les prop firms. +Tu résumes des transcripts de vidéos YouTube en français pour des traders. +Format de réponse : +- Contexte marché (1-2 phrases) +- Points clés (3-5 bullet points) +- Takeaways pour un trader prop firm (1-2 phrases) +Sois concis et direct.""" + +@app.get("/") +def root(): + return {"status": "ok", "service": "PropFirms DGX API", "version": "1.2.0"} + +@app.get("/health") +def health(): + return { + "status": "healthy", + "timestamp": datetime.utcnow().isoformat(), + "host": platform.node(), + "ollama": "qwen3:14b" + } + +@app.get("/ping") +def ping(): + return {"pong": True} + +class SummarizeRequest(BaseModel): + transcript: str + video_title: str = "" + +@app.post("/summarize") +async def summarize(req: SummarizeRequest): + if not req.transcript.strip(): + raise HTTPException(status_code=400, detail="Transcript vide") + + prompt = f"Titre de la vidéo : {req.video_title}\n\nTranscript :\n{req.transcript[:4000]}" + + payload = jsonlib.dumps({ + "model": "qwen3:14b", + "prompt": prompt, + "system": SYSTEM_PROMPT, + "stream": False + }).encode("utf-8") + + try: + request = urllib.request.Request( + f"{OLLAMA_URL}/api/generate", + data=payload, + headers={"Content-Type": "application/json"}, + method="POST" + ) + with urllib.request.urlopen(request, timeout=120) as resp: + result = jsonlib.loads(resp.read()) + except Exception as e: + raise HTTPException(status_code=502, detail=f"Erreur Ollama : {str(e)}") + + return { + "summary": result.get("response", ""), + "video_title": req.video_title, + "model": "qwen3:14b", + "timestamp": datetime.utcnow().isoformat() + } + +class OCRRequest(BaseModel): + image_base64: str + platform: str = "auto" + +@app.post("/ocr") +def ocr(req: OCRRequest): + raise HTTPException(status_code=503, detail="OCR non encore activé — disponible à l'étape 3") \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..420e8d1 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +fastapi==0.115.0 +uvicorn[standard]==0.30.6 +pydantic==2.9.0 +python-multipart==0.0.12 +httpx==0.27.2 \ No newline at end of file