Spaces:
Sleeping
Sleeping
File size: 4,909 Bytes
7b0a8d1 646538b 7b0a8d1 646538b 7b0a8d1 646538b 7b0a8d1 646538b 7b0a8d1 8f58ae6 7b0a8d1 8f58ae6 7b0a8d1 8f58ae6 7b0a8d1 8f58ae6 7b0a8d1 8f58ae6 7b0a8d1 8f58ae6 646538b 7b0a8d1 646538b 7b0a8d1 646538b 7b0a8d1 646538b 7b0a8d1 646538b 7b0a8d1 646538b 7b0a8d1 646538b f9c845b 7b0a8d1 646538b 7b0a8d1 646538b 7b0a8d1 646538b |
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 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
from fastapi import FastAPI, Request, Form
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_core.prompts import PromptTemplate
from langchain_core.runnables import RunnablePassthrough, RunnableLambda
import os
import requests
from dotenv import load_dotenv
load_dotenv()
app = FastAPI()
# Mount static files
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")
# Load FAISS Index
FAISS_PATH = "faiss_index"
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
if os.path.exists(FAISS_PATH):
vector_db = FAISS.load_local(FAISS_PATH, embeddings, allow_dangerous_deserialization=True)
retriever = vector_db.as_retriever(search_kwargs={"k": 3})
print("DEBUG: FAISS index loaded.")
else:
print("WARNING: FAISS index not found. Run ingest.py first.")
retriever = None
# Custom DeepSeek V3.2 Wrapper
def call_deepseek_v3(prompt_input):
if hasattr(prompt_input, "to_string"):
prompt_text = prompt_input.to_string()
else:
prompt_text = str(prompt_input)
api_url = "https://router.huggingface.co/v1/chat/completions"
token = os.getenv("HUGGINGFACEHUB_API_TOKEN")
if not token:
return "Error: No API Token found."
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
payload = {
"model": "deepseek-ai/DeepSeek-V3.2",
"messages": [
{
"role": "system",
"content": "You are a Stranger Things expert. Answer clearly."
},
{
"role": "user",
"content": prompt_text
}
],
"temperature": 0.3,
"max_tokens": 700,
"stream": False
}
try:
response = requests.post(api_url, headers=headers, json=payload)
if response.status_code != 200:
return f"DeepSeek Error ({response.status_code}): {response.text}"
return response.json()["choices"][0]["message"]["content"]
except Exception as e:
return f"Connection Error: {e}"
llm = RunnableLambda(call_deepseek_v3)
# Updated Prompt Template (User Request)
template = """
You are a Stranger Things expert assistant. Answer the user's question using ONLY the provided context.
Important rules:
- Do NOT copy sentences directly from the context. Rewrite in your own words.
- If the context does NOT contain the answer, say: "I don’t have enough information in the provided context to answer that fully."
- Keep the tone natural, friendly, and engaging.
- Write at least 4–6 sentences unless the question is very simple.
If the question is about a CHARACTER, you MUST include:
1) Full name + who they are in the story
2) Key relationships (friends, family, love interest, major connections)
3) Role / occupation / passion (student, sheriff, journalist, Dungeon Master, etc.)
4) Iconic traits (personality, behavior, famous moments or skills)
If the question is about an EVENT / LOCATION / OBJECT, you MUST include:
1) What it is
2) Why it matters in the story
3) Who is involved
4) Any major consequences or impact
Context:
{context}
User Question:
{question}
Answer (detailed and structured):
"""
prompt = PromptTemplate.from_template(template)
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
if retriever:
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| prompt
| llm
)
else:
rag_chain = None
@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
from pydantic import BaseModel
class QueryRequest(BaseModel):
query: str
@app.post("/query")
async def query_endpoint(request: QueryRequest):
if not rag_chain:
return {"answer": "System Error: RAG chain not initialized."}
answer = rag_chain.invoke(request.query)
return {"answer": answer}
@app.post("/get_response")
async def get_response(request: Request, query: str = Form(...)):
if not rag_chain:
return templates.TemplateResponse("index.html", {"request": request, "response": "System Error: RAG chain not initialized."})
result = rag_chain.invoke(query)
return templates.TemplateResponse("index.html", {"request": request, "response": result})
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8001)
|