File size: 4,999 Bytes
4cfde22
 
 
 
a8f24b6
 
 
 
4cfde22
 
 
 
 
 
 
 
fe64323
 
 
 
 
 
 
 
78aa1b8
a8f24b6
 
fe64323
4cfde22
 
 
 
 
b25dddd
 
 
4cfde22
 
 
 
 
 
 
 
 
 
 
b25dddd
4cfde22
b25dddd
4cfde22
b25dddd
4cfde22
b25dddd
4cfde22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b25dddd
 
 
4cfde22
 
 
 
b25dddd
 
 
 
 
 
 
 
 
 
 
 
 
4cfde22
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b25dddd
 
 
 
 
4cfde22
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# app.py
import gradio as gr
import os
from langchain_community.vectorstores import FAISS
from langchain_together import TogetherEmbeddings, Together
from langchain.prompts import ChatPromptTemplate
from langchain.schema.runnable import RunnablePassthrough
from langchain.schema.output_parser import StrOutputParser
from langchain.memory import ConversationBufferMemory
from typing import List, Tuple

# Environment variables for API keys
TOGETHER_API_KEY = os.getenv('TOGETHER_API_KEY')

class ChatBot:
    def __init__(self):
        # Initialize embeddings
        self.embeddings = TogetherEmbeddings(
            model="togethercomputer/m2-bert-80M-8k-retrieval",
            together_api_key=TOGETHER_API_KEY
        )
        
        # Load the pre-created FAISS index with embeddings
        self.vectorstore = FAISS.load_local(
            ".",
            embeddings=self.embeddings,
            allow_dangerous_deserialization=True  # Only enable this if you trust the source of the index
        )
        self.retriever = self.vectorstore.as_retriever()
        
        # Initialize the model
        self.model = Together(
            model="meta-llama/Llama-3.3-70B-Instruct-Turbo",
            temperature=0.5,
            max_tokens=150,
            top_k=30,
            together_api_key=TOGETHER_API_KEY
        )
        
        # Initialize memory
        self.memory = ConversationBufferMemory(
            return_messages=True,
            memory_key="chat_history",
            output_key="answer"
        )
        
        # Create the prompt template
        self.template = """Quyidagi kontekst va suhbat tarixiga asoslanib, savolga o'zbek tilida tabiiy tarzda javob bering:

Kontekst: {context}

Suhbat Tarixi: {chat_history}

Savol: {question}"""
        
        self.prompt = ChatPromptTemplate.from_template(self.template)
        
        # Create the chain
        self.chain = (
            {
                "context": self.retriever,
                "chat_history": lambda x: self.get_chat_history(),
                "question": RunnablePassthrough()
            }
            | self.prompt
            | self.model
            | StrOutputParser()
        )
    
    def get_chat_history(self) -> str:
        """Format chat history for the prompt"""
        messages = self.memory.load_memory_variables({})["chat_history"]
        return "\n".join([f"{m.type}: {m.content}" for m in messages])
    
    def process_response(self, response: str) -> str:
        """Clean up the response"""
        unwanted_tags = ["[INST]", "[/INST]", "<s>", "</s>"]
        for tag in unwanted_tags:
            response = response.replace(tag, "")
        return response.strip()
    
    def chat(self, message: str, history: List[Tuple[str, str]]) -> str:
        """Process a single chat message"""
        try:
            self.memory.chat_memory.add_user_message(message)
            response = self.chain.invoke(message)
            clean_response = self.process_response(response)
            
            # Agar javob to'liq bo'lmasa yoki noto'g'ri bo'lsa, qayta urinib ko'rish
            if not clean_response or len(clean_response.split()) < 3:
                clean_response = "Kechirasiz, savolingizni tushunolmadim. Iltimos, batafsilroq savol bering."
            
            self.memory.chat_memory.add_ai_message(clean_response)
            return clean_response
        except Exception as e:
            return f"Xatolik yuz berdi: {str(e)}"

    def reset_chat(self) -> List[Tuple[str, str]]:
        """Reset the chat history"""
        self.memory.clear()
        return []

# Create the Gradio interface
def create_demo() -> gr.Interface:
    chatbot = ChatBot()
    
    with gr.Blocks() as demo:
        gr.Markdown("""# Knowledge Base Chatbot
        Ask questions about your documents and get informed responses!""")
        
        chatbot_interface = gr.Chatbot(
            height=600,
            show_copy_button=True,
        )
        
        with gr.Row():
            msg = gr.Textbox(
                show_label=False,
                placeholder="Type your message here...",
                container=False
            )
            submit = gr.Button("Send", variant="primary")
        
        clear = gr.Button("New Chat")
        
        def respond(message, chat_history):
            # Foydalanuvchi xabarini tozalash
            message = message.strip()
            if not message:
                return "", chat_history
            
            bot_message = chatbot.chat(message, chat_history)
            chat_history.append((message, bot_message))
            return "", chat_history
        
        submit.click(respond, [msg, chatbot_interface], [msg, chatbot_interface])
        msg.submit(respond, [msg, chatbot_interface], [msg, chatbot_interface])
        clear.click(lambda: chatbot.reset_chat(), None, chatbot_interface)
    
    return demo

demo = create_demo()

if __name__ == "__main__":
    demo.launch()