File size: 7,065 Bytes
5f5f8de
6404fd8
5f5f8de
 
6404fd8
 
 
c2dd28c
5f5f8de
121ef90
6404fd8
5f5f8de
6404fd8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121ef90
 
6404fd8
 
121ef90
6404fd8
 
121ef90
6404fd8
121ef90
 
38dd749
6404fd8
121ef90
6404fd8
 
121ef90
6404fd8
c2dd28c
6404fd8
 
 
 
 
cb15139
6404fd8
cb15139
6404fd8
 
cb15139
6404fd8
 
cb15139
6404fd8
 
 
 
 
cb15139
6404fd8
 
 
 
 
121ef90
6404fd8
 
 
 
 
121ef90
6404fd8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a53e1b6
6404fd8
 
a53e1b6
5f5f8de
6404fd8
 
5f5f8de
6404fd8
 
105179a
6404fd8
 
 
 
 
a53e1b6
6404fd8
 
a53e1b6
6404fd8
 
cb7bbf3
6404fd8
 
cb7bbf3
6404fd8
 
 
 
 
 
121ef90
6404fd8
 
5f5f8de
 
6404fd8
121ef90
6404fd8
 
5f5f8de
6404fd8
 
5f5f8de
6404fd8
 
 
 
 
 
 
121ef90
6404fd8
 
5f5f8de
6404fd8
5f5f8de
6404fd8
5f5f8de
6404fd8
 
105179a
6404fd8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5f5f8de
6404fd8
38dd749
6404fd8
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
import gradio as gr
from typing import List, Dict
from langchain_core.prompts import ChatPromptTemplate
from langchain_community.llms.huggingface_pipeline import HuggingFacePipeline
from transformers import pipeline
import chromadb
from chromadb.utils import embedding_functions
from sentence_transformers import SentenceTransformer
import os

class ChromaDBChatbot:
    def __init__(self):
        # Initialize in-memory ChromaDB
        self.chroma_client = chromadb.Client()
        
        # Initialize embedding function
        self.embedding_function = embedding_functions.SentenceTransformerEmbeddingFunction(
            model_name="all-MiniLM-L6-v2"
        )
        
        # Create or get collection
        self.collection = self.chroma_client.create_collection(
            name="text_collection",
            embedding_function=self.embedding_function
        )

        # Initialize the model - using a smaller model suitable for CPU
        pipe = pipeline(
            "text-generation",
            model="TinyLlama/TinyLlama-1.1B-Chat-v1.0",
            max_new_tokens=512,
            temperature=0.7,
            top_p=0.95,
            repetition_penalty=1.15
        )
        self.llm = HuggingFacePipeline(pipeline=pipe)
        
        # Enhanced prompt templates
        self.templates = {
            "default": """
            IMPORTANT: You are a helpful assistant that provides information based on the retrieved context.
            
            STRICT RULES:
            1. Base your response ONLY on the provided context
            2. If you cannot find relevant information, respond with: "I apologize, but I cannot find information about that in the database."
            3. Do not make assumptions or use external knowledge
            4. Be concise and accurate in your responses
            5. If quoting from the context, clearly indicate it
            
            Context: {context}
            Chat History: {chat_history}
            Question: {question}
            
            Answer:""",
            
            "summary": """
            Create a concise summary of the following context.
            
            Context: {context}
            
            Key Requirements:
            1. Highlight the main points
            2. Keep it brief and clear
            3. Use bullet points if appropriate
            4. Include only information from the context
            
            Summary:""",
            
            "technical": """
            Provide a technical explanation based on the context.
            
            Context: {context}
            Question: {question}
            
            Guidelines:
            1. Focus on technical details
            2. Explain complex concepts clearly
            3. Use appropriate technical terminology
            4. Provide examples if present in the context
            
            Technical Explanation:"""
        }
        
        self.chat_history = ""
        self.loaded = False

    def load_data(self, file_path: str):
        """Load data into ChromaDB"""
        if self.loaded:
            return
        
        try:
            # Read the text file
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # Split into chunks (512 tokens each with 50 token overlap)
            chunk_size = 512
            overlap = 50
            chunks = []
            
            for i in range(0, len(content), chunk_size - overlap):
                chunk = content[i:i + chunk_size]
                chunks.append(chunk)
            
            # Add documents to collection
            self.collection.add(
                documents=chunks,
                ids=[f"doc_{i}" for i in range(len(chunks))]
            )
            
            self.loaded = True
            print(f"Loaded {len(chunks)} chunks into ChromaDB")
            
        except Exception as e:
            print(f"Error loading data: {str(e)}")
            return False

    def _search_chroma(self, query: str) -> List[Dict]:
        """Search ChromaDB for relevant documents"""
        try:
            results = self.collection.query(
                query_texts=[query],
                n_results=5
            )
            return [{"content": doc} for doc in results['documents'][0]]
        except Exception as e:
            print(f"Error searching ChromaDB: {str(e)}")
            return []

    def chat(self, query: str, history) -> str:
        """Process a query and return a response"""
        try:
            if not self.loaded:
                self.load_data('a2023-45.txt')
            
            # Determine template type based on query
            template_type = "default"
            if any(word in query.lower() for word in ["summarize", "summary"]):
                template_type = "summary"
            elif any(word in query.lower() for word in ["technical", "explain", "how does"]):
                template_type = "technical"
            
            # Search ChromaDB for relevant content
            search_results = self._search_chroma(query)
            
            if not search_results:
                return "I apologize, but I cannot find information about that in the database."
            
            # Extract and combine relevant content
            context = "\n\n".join([result['content'] for result in search_results])
            
            # Create prompt with selected template
            prompt = ChatPromptTemplate.from_template(self.templates[template_type])
            
            # Generate response using LLM
            chain = prompt | self.llm
            result = chain.invoke({
                "context": context,
                "chat_history": self.chat_history,
                "question": query
            })
            
            # Update chat history
            self.chat_history += f"\nUser: {query}\nAI: {result}\n"
            
            return result
        except Exception as e:
            return f"Error processing query: {str(e)}"

# Initialize the chatbot
chatbot = ChromaDBChatbot()

# Create the Gradio interface
demo = gr.Interface(
    fn=chatbot.chat,
    inputs=[
        gr.Textbox(
            label="Your Question",
            placeholder="Ask anything about the document...",
            lines=2
        ),
        gr.State([])  # For chat history
    ],
    outputs=gr.Textbox(label="Answer", lines=10),
    title="ChromaDB-powered Document Q&A",
    description="""
    Ask questions about your document:
    - For summaries, include words like 'summarize' or 'summary'
    - For technical details, use words like 'technical', 'explain', 'how does'
    - For general questions, just ask normally
    """,
    examples=[
        ["Can you summarize the main points?"],
        ["What are the technical details about this topic?"],
        ["Give me a general overview of the content."],
    ],
    theme=gr.themes.Soft()
)

# Launch the interface
if __name__ == "__main__":
    demo.launch()