Update app.py
Browse files
app.py
CHANGED
|
@@ -10,32 +10,31 @@ import requests
|
|
| 10 |
import nest_asyncio
|
| 11 |
import uvicorn
|
| 12 |
|
| 13 |
-
# ✅ Load
|
| 14 |
with open("texts.json", "r", encoding="utf-8") as f:
|
| 15 |
texts = json.load(f)
|
| 16 |
|
| 17 |
index = faiss.read_index("faiss_index.bin")
|
| 18 |
embed_model = SentenceTransformer("all-MiniLM-L6-v2")
|
| 19 |
|
|
|
|
| 20 |
API_KEY = os.environ.get("OPENROUTER_API_KEY")
|
| 21 |
MODEL = "qwen/qwq-32b:free"
|
| 22 |
|
| 23 |
-
# ✅ FastAPI app
|
| 24 |
app = FastAPI()
|
| 25 |
|
| 26 |
-
# ✅ Context
|
| 27 |
def get_context(query, top_k=5, threshold=0.3):
|
| 28 |
query_vec = embed_model.encode([query])
|
| 29 |
D, I = index.search(np.array(query_vec), top_k)
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
if not results:
|
| 34 |
return ""
|
| 35 |
|
| 36 |
-
return "\n".join([text for text, _ in
|
| 37 |
|
| 38 |
-
# ✅
|
| 39 |
def chat_fn(message, history):
|
| 40 |
headers = {
|
| 41 |
"Authorization": f"Bearer {API_KEY}",
|
|
@@ -45,15 +44,15 @@ def chat_fn(message, history):
|
|
| 45 |
context = get_context(message)
|
| 46 |
|
| 47 |
if not context.strip():
|
| 48 |
-
return "❌
|
| 49 |
|
| 50 |
messages = [
|
| 51 |
{
|
| 52 |
"role": "system",
|
| 53 |
"content": (
|
| 54 |
-
"You are a concise
|
| 55 |
-
"
|
| 56 |
-
"'
|
| 57 |
)
|
| 58 |
}
|
| 59 |
]
|
|
@@ -67,39 +66,47 @@ def chat_fn(message, history):
|
|
| 67 |
payload = {
|
| 68 |
"model": MODEL,
|
| 69 |
"messages": messages,
|
| 70 |
-
"max_tokens": 200
|
| 71 |
}
|
| 72 |
|
| 73 |
try:
|
| 74 |
-
response = requests.post(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
response.raise_for_status()
|
| 76 |
reply = response.json()["choices"][0]["message"]["content"]
|
| 77 |
except Exception as e:
|
| 78 |
-
reply = f"
|
| 79 |
|
| 80 |
-
return reply
|
| 81 |
|
| 82 |
-
# ✅
|
| 83 |
@app.post("/chat")
|
| 84 |
async def chat_api(request: Request):
|
| 85 |
body = await request.json()
|
| 86 |
-
message = body.get("message")
|
| 87 |
history = body.get("history", [])
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
response = chat_fn(message, history)
|
| 89 |
return JSONResponse(content={"response": response})
|
| 90 |
|
| 91 |
-
# ✅ Gradio
|
| 92 |
demo = gr.ChatInterface(
|
| 93 |
fn=chat_fn,
|
| 94 |
-
title="CODEX MIRXA KAMRAN",
|
| 95 |
-
description="
|
| 96 |
theme="soft"
|
| 97 |
)
|
| 98 |
|
| 99 |
-
# ✅ Mount Gradio at root
|
| 100 |
app = gr.mount_gradio_app(app, demo, path="/")
|
| 101 |
|
| 102 |
-
# ✅
|
| 103 |
if __name__ == "__main__":
|
| 104 |
nest_asyncio.apply()
|
| 105 |
uvicorn.run(app, host="0.0.0.0", port=7860)
|
|
|
|
| 10 |
import nest_asyncio
|
| 11 |
import uvicorn
|
| 12 |
|
| 13 |
+
# ✅ Load documents and FAISS index
|
| 14 |
with open("texts.json", "r", encoding="utf-8") as f:
|
| 15 |
texts = json.load(f)
|
| 16 |
|
| 17 |
index = faiss.read_index("faiss_index.bin")
|
| 18 |
embed_model = SentenceTransformer("all-MiniLM-L6-v2")
|
| 19 |
|
| 20 |
+
# ✅ API keys and config
|
| 21 |
API_KEY = os.environ.get("OPENROUTER_API_KEY")
|
| 22 |
MODEL = "qwen/qwq-32b:free"
|
| 23 |
|
|
|
|
| 24 |
app = FastAPI()
|
| 25 |
|
| 26 |
+
# ✅ Context fetcher
|
| 27 |
def get_context(query, top_k=5, threshold=0.3):
|
| 28 |
query_vec = embed_model.encode([query])
|
| 29 |
D, I = index.search(np.array(query_vec), top_k)
|
| 30 |
+
|
| 31 |
+
matches = [(texts[i], d) for i, d in zip(I[0], D[0]) if d >= threshold]
|
| 32 |
+
if not matches:
|
|
|
|
| 33 |
return ""
|
| 34 |
|
| 35 |
+
return "\n".join([text for text, _ in matches])
|
| 36 |
|
| 37 |
+
# ✅ Core chat function
|
| 38 |
def chat_fn(message, history):
|
| 39 |
headers = {
|
| 40 |
"Authorization": f"Bearer {API_KEY}",
|
|
|
|
| 44 |
context = get_context(message)
|
| 45 |
|
| 46 |
if not context.strip():
|
| 47 |
+
return "❌ I couldn’t find any relevant info to answer that. Please ask something else."
|
| 48 |
|
| 49 |
messages = [
|
| 50 |
{
|
| 51 |
"role": "system",
|
| 52 |
"content": (
|
| 53 |
+
"You are a precise, concise assistant. Use ONLY the provided context to answer."
|
| 54 |
+
" Do not make up facts. Answer briefly and clearly. If unsure, respond with:"
|
| 55 |
+
" 'I couldn’t find the answer based on available context.'\n\nContext:\n" + context
|
| 56 |
)
|
| 57 |
}
|
| 58 |
]
|
|
|
|
| 66 |
payload = {
|
| 67 |
"model": MODEL,
|
| 68 |
"messages": messages,
|
| 69 |
+
"max_tokens": 200,
|
| 70 |
}
|
| 71 |
|
| 72 |
try:
|
| 73 |
+
response = requests.post(
|
| 74 |
+
"https://openrouter.ai/api/v1/chat/completions",
|
| 75 |
+
headers=headers,
|
| 76 |
+
json=payload,
|
| 77 |
+
timeout=30 # Prevent hanging
|
| 78 |
+
)
|
| 79 |
response.raise_for_status()
|
| 80 |
reply = response.json()["choices"][0]["message"]["content"]
|
| 81 |
except Exception as e:
|
| 82 |
+
reply = f"⚠️ API error: {str(e)[:100]}"
|
| 83 |
|
| 84 |
+
return reply.strip()
|
| 85 |
|
| 86 |
+
# ✅ POST endpoint for API usage
|
| 87 |
@app.post("/chat")
|
| 88 |
async def chat_api(request: Request):
|
| 89 |
body = await request.json()
|
| 90 |
+
message = body.get("message", "").strip()
|
| 91 |
history = body.get("history", [])
|
| 92 |
+
|
| 93 |
+
if not message:
|
| 94 |
+
return JSONResponse(content={"response": "⚠️ Please enter a valid message."})
|
| 95 |
+
|
| 96 |
response = chat_fn(message, history)
|
| 97 |
return JSONResponse(content={"response": response})
|
| 98 |
|
| 99 |
+
# ✅ Gradio interface
|
| 100 |
demo = gr.ChatInterface(
|
| 101 |
fn=chat_fn,
|
| 102 |
+
title="💬 CODEX MIRXA KAMRAN",
|
| 103 |
+
description="Ask anything related to our knowledge base. Fast, short and precise responses!",
|
| 104 |
theme="soft"
|
| 105 |
)
|
| 106 |
|
|
|
|
| 107 |
app = gr.mount_gradio_app(app, demo, path="/")
|
| 108 |
|
| 109 |
+
# ✅ Local run
|
| 110 |
if __name__ == "__main__":
|
| 111 |
nest_asyncio.apply()
|
| 112 |
uvicorn.run(app, host="0.0.0.0", port=7860)
|