File size: 3,864 Bytes
5836b9c
 
bc58bf4
 
5836b9c
bc58bf4
 
 
5836b9c
b7552f5
 
bc58bf4
7b56da7
bc58bf4
 
 
 
 
 
7b56da7
bc58bf4
896a65e
bc58bf4
5836b9c
 
896a65e
53bc750
896a65e
 
 
 
53bc750
 
7b56da7
01817d1
bc58bf4
 
7b56da7
 
 
01817d1
 
7b56da7
01817d1
7b56da7
bc58bf4
 
 
 
 
 
 
5836b9c
96bb719
01817d1
53bc750
96bb719
 
01817d1
96bb719
5836b9c
01817d1
 
be128ec
96bb719
 
 
 
53bc750
be128ec
01817d1
5836b9c
bc58bf4
 
 
 
 
96bb719
bc58bf4
be128ec
 
 
96bb719
be128ec
bc58bf4
 
7b56da7
 
 
 
53bc750
7b56da7
bc58bf4
 
 
7b56da7
bc58bf4
7b56da7
bc58bf4
7b56da7
5836b9c
 
 
7b56da7
5836b9c
7b56da7
 
 
 
5836b9c
 
 
7b56da7
5836b9c
bc58bf4
7b56da7
96bb719
bc58bf4
 
 
b7552f5
 
7b56da7
b7552f5
 
 
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
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import gradio as gr
import os
import json
import faiss
import numpy as np
from sentence_transformers import SentenceTransformer
import requests
import nest_asyncio
import uvicorn

# βœ… Load documents and FAISS index
with open("texts.json", "r", encoding="utf-8") as f:
    texts = json.load(f)

index = faiss.read_index("faiss_index.bin")
embed_model = SentenceTransformer("all-MiniLM-L6-v2")

# βœ… API keys and config
API_KEY = os.environ.get("OPENROUTER_API_KEY")
MODEL = "nousresearch/deephermes-3-llama-3-8b-preview:free"  # Updated model

app = FastAPI()

# βœ… Greeting checker with added variations
def is_greeting(text):
    greetings = [
        "hi", "hello", "hey", "good morning", "good afternoon", "good evening",
        "howdy", "yo", "sup", "greetings", "what's up", "hey there"
    ]
    return any(g in text.lower() for g in greetings)

# βœ… Context fetcher
def get_context(query, top_k=5, threshold=0.3):
    query_vec = embed_model.encode([query])
    D, I = index.search(np.array(query_vec), top_k)
    
    matches = [(texts[i], d) for i, d in zip(I[0], D[0]) if d >= threshold]
    if not matches:
        return ""
    
    return "\n".join([text for text, _ in matches])

# βœ… Core chat function
def chat_fn(message, history):
    headers = {
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json"
    }

    context = get_context(message)

    # βœ… Handle greetings when no context found
    if not context.strip():
        if is_greeting(message):
            return "πŸ‘‹ Hey there! How can I help you today?"
        return "πŸ€” Hmm, I’m not sure about that. Could you rephrase your question?"

    # βœ… Construct prompt with friendly natural tone
    messages = [
        {
            "role": "system",
            "content": (
                "You are a friendly, helpful assistant."
                " Use the following context to answer questions naturally and clearly."
                " Be conversational and concise. Avoid saying you're using context."
                " If unsure, say: 'I’m not sure about that. Could you rephrase?'"
                "\n\nContext:\n" + context
            )
        }
    ]

    for user, assistant in history:
        messages.append({"role": "user", "content": user})
        messages.append({"role": "assistant", "content": assistant})

    messages.append({"role": "user", "content": message + "\n\nKeep your reply short and natural."})

    payload = {
        "model": MODEL,
        "messages": messages,
        "max_tokens": 200,
    }

    try:
        response = requests.post(
            "https://openrouter.ai/api/v1/chat/completions",
            headers=headers,
            json=payload,
            timeout=30
        )
        response.raise_for_status()
        reply = response.json()["choices"][0]["message"]["content"]
    except Exception as e:
        reply = f"⚠️ API error: {str(e)[:100]}"

    return reply.strip()

# βœ… POST endpoint for API usage
@app.post("/chat")
async def chat_api(request: Request):
    body = await request.json()
    message = body.get("message", "").strip()
    history = body.get("history", [])
    
    if not message:
        return JSONResponse(content={"response": "⚠️ Please enter a valid message."})
    
    response = chat_fn(message, history)
    return JSONResponse(content={"response": response})

# βœ… Gradio interface
demo = gr.ChatInterface(
    fn=chat_fn,
    title="πŸ’¬ CODEX MIRXA KAMRAN",
    description="Chat with our AI assistant based on internal knowledge. Short, natural and helpful answers!",
    theme="soft"
)

app = gr.mount_gradio_app(app, demo, path="/")

# βœ… Local run
if __name__ == "__main__":
    nest_asyncio.apply()
    uvicorn.run(app, host="0.0.0.0", port=7860)