File size: 3,790 Bytes
e2412ee
725b2c0
e2412ee
725b2c0
 
 
 
 
 
e2412ee
725b2c0
e2412ee
725b2c0
e2412ee
725b2c0
0ab4c23
725b2c0
 
81238fa
725b2c0
 
0ab4c23
e2412ee
725b2c0
0ab4c23
 
725b2c0
0ab4c23
 
 
 
e2412ee
725b2c0
 
 
 
81b4c7c
725b2c0
 
 
81b4c7c
725b2c0
 
 
 
 
 
 
 
 
 
 
 
 
81b4c7c
725b2c0
 
 
 
 
 
81b4c7c
725b2c0
81b4c7c
725b2c0
 
 
 
 
 
 
 
 
0ab4c23
725b2c0
 
 
 
0ab4c23
 
81b4c7c
725b2c0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81b4c7c
725b2c0
 
81b4c7c
725b2c0
 
 
 
e2412ee
725b2c0
e2412ee
725b2c0
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import os
import requests
from dotenv import load_dotenv
from fastapi import FastAPI, File, Form, UploadFile
from fastapi.responses import StreamingResponse, JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import List, Optional
import uvicorn

# Load environment variables
load_dotenv()
HF_TOKEN = os.environ.get("CHAT_MATE")

# ---------------- FastAPI setup ----------------
app = FastAPI(
    title="ChatMate API",
    description="Stream replies from Hugging Face Space and upload requirement docs.",
    version="1.0",
    docs_url="/apidocs",   # Swagger UI
    redoc_url="/redoc"     # ReDoc UI
)

# Allow all CORS (for browser testing)
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# ---------------- Models ----------------
class HistoryItem(BaseModel):
    role: str
    content: str

class ChatRequest(BaseModel):
    message: str
    history: Optional[List[HistoryItem]] = []

# ---------------- Endpoints ----------------
@app.post(
    "/chat-stream",
    summary="Stream assistant reply or image",
    description="Send a message and history, receive either a streamed text reply or base64-encoded image.",
    response_description="Streamed reply or image base64",
    responses={
        200: {"content": {"text/plain": {}}}
    },
    tags=["Chat"]
)
async def chat_stream(request_data: ChatRequest):
    headers = {"Authorization": f"Bearer {HF_TOKEN}"}

    response = requests.post(
        "https://fredericksundeep-chatmateapi.hf.space/chat-stream",
        json=request_data.dict(),
        headers=headers,
        stream=True
    )

    return StreamingResponse(response.iter_content(decode_unicode=True), media_type="text/plain")

@app.post(
    "/chat-stream-doc",
    summary="Upload requirement doc & generate downloadable project code (ZIP)",
    description="Upload a PDF/TXT requirement document with stack preferences, and receive the scaffolded project code as a downloadable .zip file.",
    responses={
        200: {"content": {"application/zip": {}}}
    },
    tags=["Chat"]
)
async def chat_stream_doc(
    file: UploadFile = File(..., description="Requirement document (PDF or TXT)"),
    frontend: str = Form(..., description="Frontend tech (React, Angular, etc.)"),
    backend: str = Form(..., description="Backend tech (Flask, Node.js, etc.)"),
    database: str = Form(..., description="Database (MongoDB, PostgreSQL, etc.)")
):
    headers = {"Authorization": f"Bearer {HF_TOKEN}"}

    files = {
        "file": (file.filename, file.file, file.content_type)
    }
    data = {
        "frontend": frontend,
        "backend": backend,
        "database": database
    }

    try:
        response = requests.post(
            "https://fredericksundeep-aimateapis.hf.space/chat-stream-doc",
            headers=headers,
            files=files,
            data=data
        )

        return StreamingResponse(
            iter([response.content]),
            media_type=response.headers.get("Content-Type", "application/octet-stream"),
            headers={
                "Content-Disposition": response.headers.get(
                    "Content-Disposition",
                    "attachment; filename=generated_project.zip"
                )
            }
        )

    except Exception as e:
        return JSONResponse(content={"error": str(e)}, status_code=500)

# ---------------- Startup warm-up ----------------
@app.on_event("startup")
async def warmup():
    print("🔧 Warming up...")

# ---------------- Run ----------------
if __name__ == "__main__":
    port = int(os.environ.get("PORT", 7860))
    uvicorn.run("app:app", host="0.0.0.0", port=port, reload=False)