FinanceEducationAssistant / src /data /VariationGenerator.py
Fade0510's picture
Cleaned up code before reimplementing semantic cache
6710fbe
Raw
History Blame Contribute Delete
4.27 kB
import json
import re
import time
from typing import List
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
class VariationGenerator:
def __init__(
self,
category: str = "finance",
model: str = "gpt-4o-mini",
temperature: float = 0.3,
output_file: str = "financial_kb_output.json"
):
self.category = category
self.output_file = output_file
self.llm = ChatOpenAI(
model=model,
temperature=temperature
)
# =========================
# LOAD QUESTIONS FROM FILE
# =========================
def load_questions(self, file_path: str) -> List[str]:
with open(file_path, "r") as f:
lines = [line.strip() for line in f if line.strip()]
print(f"✅ Loaded {len(lines)} questions from {file_path}")
return lines
# =========================
# CLEAN QUESTION
# =========================
def clean_question(self, question: str) -> str:
question = question.strip()
# remove extra spaces before ?
question = re.sub(r"\s+\?", "?", question)
# ensure first letter capitalized
question = question[0].upper() + question[1:]
if not question.endswith("?"):
question += "?"
return question
# =========================
# KEYWORDS
# =========================
def extract_keywords(self, question: str) -> List[str]:
words = re.sub(r"[^\w\s]", "", question.lower()).split()
stop_words = {"what", "is", "the", "a", "an", "how", "does", "do"}
keywords = [w for w in words if w not in stop_words]
return keywords[:5]
# =========================
# VARIATIONS
# =========================
def generate_variations(self, question: str) -> List[str]:
base = question.replace("?", "").lower()
variations = [
f"What is {base}?",
f"Can you explain {base}?",
f"How does {base} work?",
f"What does {base} mean?",
f"How do I understand {base}?",
f"Can you give a simple explanation of {base}?"
]
# Remove duplicates
return list(set(variations))
# =========================
# LLM ANSWER
# =========================
def generate_answer(self, question: str) -> str:
prompt = f"""
You are a financial expert.
Answer the question clearly and concisely.
Rules:
- Max 3 sentences
- Beginner friendly
- No fluff
- No repetition
Question:
{question}
"""
response = self.llm.invoke(prompt)
return response.content.strip()
# =========================
# BUILD RECORD
# =========================
def build_record(self, question: str, record_id: int) -> dict:
clean_q = self.clean_question(question)
return {
"id": record_id,
"category": self.category,
"question": clean_q,
"answer": self.generate_answer(clean_q),
"keywords": self.extract_keywords(clean_q),
"variations": self.generate_variations(clean_q)
}
# =========================
# PROCESS ALL QUESTIONS
# =========================
def process_file(self, input_file: str):
questions = self.load_questions("kb_unique_questions.txt")
records = []
for idx, q in enumerate(questions, start=1):
try:
record = self.build_record(q, idx)
records.append(record)
print(f"✅ Processed {idx}: {record['question']}")
# Prevent rate limiting
time.sleep(0.5)
except Exception as e:
print(f"❌ Failed at {idx}: {q} | Error: {e}")
self.save_to_json(records)
# =========================
# SAVE ALL RECORDS
# =========================
def save_to_json(self, records: List[dict]):
with open(self.output_file, "w") as f:
json.dump(records, f, indent=2)
print(f"💾 Saved {len(records)} records to {self.output_file}")
if __name__ == "__main__":
load_dotenv()
generator = VariationGenerator()
generator.process_file("kb_unique_questions.txt")