Spaces:
Sleeping
Sleeping
File size: 9,026 Bytes
64fbadd 7c4f775 64fbadd 52f8edc 64fbadd 7c4f775 64fbadd 7c4f775 64fbadd e580bee |
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 204 205 206 207 208 209 210 211 212 213 |
# main.py
import torch
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.llms import LlamaCpp
from langchain.memory import ConversationBufferMemory
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.prompts import PromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate, ChatPromptTemplate
import os
import argparse # For command-line arguments
# Import the logic functions from src
import pipeline
# --- Global Objects & Setup ---
# (Similar setup as app.py, load models, prompts etc.)
print("--- Starting Local Execution Setup ---")
# 1. Check/Define Model Path
model_name = "mistral-7b-instruct-v0.1.Q4_K_M.gguf"
if not os.path.exists(model_name):
print(f"ERROR: Model file '{model_name}' not found. Please download it first.")
exit()
# 2. Prepare Default Sample Data (Optional, for context testing)
default_reviews_text = """...""" # Paste default laptop reviews
default_reviews_list = [r.strip() for r in default_reviews_text.strip().split('---') if r.strip()]
# 3. Load Embedding Model, Text Splitter
print("Loading embedding model and text splitter...")
model_kwargs = {'device': 'cuda' if torch.cuda.is_available() else 'cpu'}
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2", model_kwargs=model_kwargs)
text_splitter = RecursiveCharacterTextSplitter(chunk_size=250, chunk_overlap=40)
# 4. Create Default Vector Store
print("Creating default FAISS vector store...")
default_vector_store = pipeline.create_vector_store_from_content(
"\n---\n".join(default_reviews_list), text_splitter, embeddings
)
if default_vector_store is None: raise ValueError("Failed to create default vector store!")
# 5. Load the LLM
print("Loading LLM (Mistral-7B GGUF)...")
llm = LlamaCpp(
model_path=model_name, n_gpu_layers=0, n_batch=512, n_ctx=4096,
f16_kv=True, temperature=0.0, max_tokens=512, verbose=False,
stop=["[/INST]", "User:", "Assistant:"]
)
# 6. Define All Prompts
print("Defining all prompts...")
# -- Phase 1 --
summary_template = """[INST] ... Reviews:\n{reviews} [/INST]\nConcise Summary:"""
summary_prompt = PromptTemplate(template=summary_template, input_variables=["reviews"])
aspect_template = """[INST] ... Reviews:\n{reviews} [/INST]\nKey Pros and Cons:"""
aspect_prompt = PromptTemplate(template=aspect_template, input_variables=["reviews"])
sentiment_template = """[INST] ... Reviews:\n{reviews} [/INST]\nOverall Sentiment (Score 1-10):"""
sentiment_prompt = PromptTemplate(template=sentiment_template, input_variables=["reviews"])
# -- Phase 2 --
condense_question_template = """[INST] Given the following conversation... Follow Up Input: {question} [/INST]\nStandalone question:"""
CONDENSE_QUESTION_PROMPT = PromptTemplate.from_template(condense_question_template)
qa_system_prompt = """[INST]
You are a factual assistant that answers only using the provided product reviews.
If the reviews include partial or uncertain information, summarize what they say.
If there is no information at all about the user’s question, respond with:
"I'm sorry, there isn't enough information in the reviews to answer that."
Do not use or infer information about price, comparisons to other brands, or availability unless they are directly mentioned in the reviews.
Always include a short "Evidence:" sentence if you found relevant mentions.
Context:
{context}
User question:
{question}
[/INST]
"""
qa_prompt = ChatPromptTemplate.from_messages([SystemMessagePromptTemplate.from_template(qa_system_prompt), HumanMessagePromptTemplate.from_template("Context:\n{context}\n\nQuestion:\n{question}\n\nHelpful Answer:")])
intent_template = """
[INST]
**CRITICAL INSTRUCTION:** Classify the user's query into ONLY ONE of two categories: "Product" or "Off-Topic".
Your response MUST be EXACTLY "Product" or EXACTLY "Off-Topic".
**EXAMPLES:**
Query: How is the battery life?
Classification: Product
Query: What are the complaints about the screen?
Classification: Product
Query: Does it come in blue?
Classification: Product
Query: What is the capital of France?
Classification: Off-Topic
Query: Hello there
Classification: Off-Topic
Query: Who are you?
Classification: Off-Topic
**NOW CLASSIFY THIS QUERY:**
Query: {query}
[/INST]
Classification:"""
intent_prompt = PromptTemplate(template=intent_template, input_variables=["query"])
# 7. Memory Object (Needed for chatbot logic)
chat_memory = ConversationBufferMemory(memory_key='chat_history', return_messages=True, output_key='answer')
print("--- Local Setup Complete ---")
# --- Main Execution Logic ---
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Run ReviewSense Analysis or Chat locally.")
parser.add_argument("--mode", choices=['analyze', 'chat'], required=True, help="Mode to run: 'analyze' reviews from a file, or 'chat' interactively.")
parser.add_argument("--input", type=str, help="Path to input .txt file for 'analyze' mode, or initial query for 'chat' mode.")
parser.add_argument("--context", type=str, help="Optional: Path to a .txt file to use as context for 'chat' mode (defaults to built-in laptop reviews).")
args = parser.parse_args()
# --- ANALYZE MODE ---
if args.mode == 'analyze':
if not args.input or not os.path.exists(args.input):
print(f"Error: Input file '{args.input}' not found for analyze mode.")
exit()
print(f"\n--- Running Analysis on: {args.input} ---")
try:
with open(args.input, 'r', encoding='utf-8') as f:
review_content = f.read()
except Exception as e:
print(f"Error reading input file: {e}")
exit()
summary, aspects, sentiment = pipeline.analyze_reviews_logic(
review_content, llm, summary_prompt, aspect_prompt, sentiment_prompt
)
print("\n--- Analysis Results ---")
print("\n[Summary]")
print(summary)
print("\n[Aspects]")
print(aspects)
print("\n[Sentiment]")
print(sentiment)
# --- CHAT MODE ---
elif args.mode == 'chat':
print("\n--- Starting Interactive Chat ---")
# Determine context
chat_vector_store = default_vector_store
context_name = "Default Laptop Reviews"
if args.context:
if not os.path.exists(args.context):
print(f"Warning: Context file '{args.context}' not found. Using default context.")
else:
print(f"Loading context from: {args.context}")
try:
with open(args.context, 'r', encoding='utf-8') as f:
context_content = f.read()
chat_vector_store = pipeline.create_vector_store_from_content(
context_content, text_splitter, embeddings
)
if chat_vector_store:
context_name = f"File: {os.path.basename(args.context)}"
else:
print("Failed to load context file. Using default context.")
chat_vector_store = default_vector_store
except Exception as e:
print(f"Error reading context file '{args.context}': {e}. Using default context.")
chat_vector_store = default_vector_store
print(f"Using context: {context_name}")
chat_memory.clear() # Start fresh chat session
# Handle initial query if provided
if args.input:
print("\nUser:", args.input)
response = pipeline.get_chatbot_response(
message=args.input,
chat_memory=chat_memory,
vector_store=chat_vector_store,
llm=llm,
intent_prompt=intent_prompt,
condense_prompt=CONDENSE_QUESTION_PROMPT,
qa_prompt=qa_prompt
)
print("\nAssistant:", response)
# Interactive loop
print("\nEnter your questions (type 'quit' or 'exit' to stop):")
while True:
try:
user_message = input("\nUser: ")
if user_message.lower() in ['quit', 'exit']:
break
if not user_message:
continue
response = pipeline.get_chatbot_response(
message=user_message,
chat_memory=chat_memory,
vector_store=chat_vector_store,
llm=llm,
intent_prompt=intent_prompt,
condense_prompt=CONDENSE_QUESTION_PROMPT,
qa_prompt=qa_prompt
)
print("\nAssistant:", response)
except EOFError: # Handle Ctrl+D
break
except KeyboardInterrupt: # Handle Ctrl+C
break
print("\n--- Chat session ended. ---")
print("\n--- Local Execution Finished ---")
|