Download claimbotics_engine.py from rahulHires/LAST_DATE: direct link, hf CLI and curl.
- Browser
- Download file 23.2 kB
-
https://huggingface.co/rahulHires/LAST_DATE/resolve/main/claimbotics_engine.py
- Command line
-
hf download hf://rahulHires/LAST_DATE/claimbotics_engine.py
-
curl -L -o claimbotics_engine.py https://huggingface.co/rahulHires/LAST_DATE/resolve/main/claimbotics_engine.py
23.2 kB
| import os | |
| import re | |
| import json | |
| import torch | |
| import pandas as pd | |
| from sentence_transformers import SentenceTransformer, util | |
| from transformers import AutoTokenizer, AutoModelForSeq2SeqLM | |
| import os, json, datetime | |
| def load_training_data(data_folder): | |
| data = [] | |
| missing_code = 0 | |
| missing_query = 0 | |
| for file in os.listdir(data_folder): | |
| if file.endswith(".json"): | |
| path = os.path.join(data_folder, file) | |
| with open(path, "r", encoding="utf-8") as f: | |
| try: | |
| entries = json.load(f) | |
| for e in entries: | |
| query_text = e.get("english") or e.get("English") or e.get("query") or e.get("Query") | |
| if not query_text: | |
| missing_query += 1 | |
| continue | |
| code_text = e.get("pandas_code") or e.get("Pandas_Code") or e.get("code") | |
| if not code_text: | |
| missing_code += 1 | |
| continue | |
| data.append({"english": query_text, "pandas_code": code_text}) | |
| except Exception as e: | |
| print(f" Skipped {file}: {e}") | |
| print(f" Loaded {len(data)} valid queryβcode pairs from {data_folder}") | |
| print(f" Skipped {missing_code} missing-code and {missing_query} missing-query entries.") | |
| return data | |
| class EnhancedRetriever: | |
| def __init__(self, data): | |
| self.model = SentenceTransformer("all-MiniLM-L6-v2") | |
| valid_data = [item for item in data if (item.get("pandas_code") and (item.get("english") or item.get("query")))] | |
| if not valid_data: | |
| raise ValueError("No valid queryβcode pairs found in dataset!") | |
| self.queries = [item.get("english") or item.get("query") for item in valid_data] | |
| self.codes = [item["pandas_code"] for item in valid_data] | |
| print(f" Using {len(valid_data)} valid items for retrieval.") | |
| print(" Encoding queries for retrieval...") | |
| self.query_embeddings = self.model.encode(self.queries, convert_to_tensor=True) | |
| def retrieve_best_match(self, user_query, top_k=3): | |
| user_emb = self.model.encode(user_query, convert_to_tensor=True) | |
| similarity = util.pytorch_cos_sim(user_emb, self.query_embeddings)[0] | |
| top_results = torch.topk(similarity, k=top_k) | |
| results = [] | |
| for i in range(top_k): | |
| results.append({ | |
| "query": self.queries[top_results.indices[i]], | |
| "pandas_code": self.codes[top_results.indices[i]], | |
| "similarity": float(top_results.values[i]) | |
| }) | |
| return results | |
| class Generator: | |
| def __init__(self, model_dir="model"): | |
| try: | |
| self.tokenizer = AutoTokenizer.from_pretrained(model_dir) | |
| self.model = AutoModelForSeq2SeqLM.from_pretrained(model_dir) | |
| print(" Base model loaded successfully.") | |
| except Exception as e: | |
| print(f" Error loading base model: {e}") | |
| self.tokenizer = None | |
| self.model = None | |
| def generate(self, query): | |
| print("\n================= GENERATE DEBUG =================") | |
| print("Incoming Query :", query) | |
| try: | |
| prompt = query | |
| print("Prompt Created:", prompt) | |
| print("Tokenizer Loaded:", self.tokenizer is not None) | |
| try: | |
| inputs = self.tokenizer(prompt, return_tensors="pt") | |
| except Exception as e: | |
| print(" TOKENIZER ERROR:", e) | |
| return f"[Tokenizer Error] {str(e)}" | |
| print("Model Loaded:", self.model is not None) | |
| try: | |
| outputs = self.model.generate(**inputs, max_length=128) | |
| print("Model Generation Successful") | |
| except Exception as e: | |
| print(" MODEL ERROR:", e) | |
| return f"[Model Error] {str(e)}" | |
| try: | |
| decoded = self.tokenizer.decode(outputs[0], skip_special_tokens=True) | |
| print("Decoding Successful β", decoded) | |
| except Exception as e: | |
| print(" DECODING ERROR:", e) | |
| return f"[Decode Error] {str(e)}" | |
| return decoded | |
| except Exception as e: | |
| print(" UNEXPECTED ERROR:", e) | |
| return f"[Unexpected Error] {str(e)}" | |
| def normalize_name(name): | |
| if not isinstance(name, str): | |
| return name | |
| return re.sub(r'[^a-z0-9]', '', name.lower()) | |
| def extract_column_names(text): | |
| words = re.findall(r'\b[a-zA-Z_][a-zA-Z0-9_]*\b', text) | |
| stopwords = { | |
| 'show','display','find','get','the','and','or','where','what','how','many','much','list','give','me','all','with','for','bottom','top','average','mean','sum','median','count','minimum','maximum','highest','lowest' | |
| } | |
| cols = [w for w in words if w.lower() not in stopwords and len(w) > 2] | |
| return [normalize_name(c) for c in cols] | |
| def extract_values(text): | |
| quoted = re.findall(r"'([^']*)'", text) | |
| numbers = re.findall(r'\b\d+\b', text) | |
| return quoted + numbers | |
| def enhanced_adaptation(user_query, code, original_retrieved_query): | |
| query_columns = extract_column_names(user_query) | |
| original_columns = extract_column_names(original_retrieved_query) | |
| query_values = extract_values(user_query) | |
| original_values = extract_values(original_retrieved_query) | |
| new_code = code | |
| for orig_col, new_col in zip(original_columns, query_columns): | |
| if orig_col and new_col and normalize_name(orig_col) != normalize_name(new_col): | |
| for pattern in [rf"'{orig_col}'", rf'\"{orig_col}\"', rf"\\b{orig_col}\\b"]: | |
| new_code = re.sub(pattern, new_col, new_code, flags=re.IGNORECASE) | |
| for orig_val, new_val in zip(original_values, query_values): | |
| if orig_val and new_val and orig_val != new_val: | |
| new_code = re.sub(rf"'{re.escape(orig_val)}'", f"'{new_val}'", new_code) | |
| new_code = re.sub(rf'\"{re.escape(orig_val)}\"', f'\"{new_val}\"', new_code) | |
| new_code = re.sub(rf"\\b{re.escape(orig_val)}\\b", new_val, new_code) | |
| return new_code | |
| def adapt_operations_based_on_query(query, code): | |
| q = query.lower() | |
| c = code | |
| if any(word in q for word in ["average", "mean", "avg"]): | |
| c = re.sub(r"\.(sum|min|max|count)\(\)", ".mean()", c) | |
| elif any(word in q for word in ["total", "sum", "add", "together"]): | |
| c = re.sub(r"\.(mean|min|max|count)\(\)", ".sum()", c) | |
| return c | |
| def select_best_template(retrieved_results, user_query): | |
| best_score = -1 | |
| best_result = retrieved_results[0] | |
| for result in retrieved_results: | |
| score = result["similarity"] | |
| if score > best_score: | |
| best_score = score | |
| best_result = result | |
| return best_result | |
| def post_process_code(code, user_query): | |
| code = re.sub(r'\.\.', '.', code) | |
| return code | |
| def detect_vague_query(user_query): | |
| q = user_query.lower() | |
| intent_keywords = [ | |
| "amount", "sum", "total", "average", "mean", "minimum", "maximum", | |
| "count", "number", "list", "show", "display", "details", "records","how many","what is" | |
| ] | |
| data_keywords = [ | |
| "claim", "bill", "policy", "approved", "rejected", "tariff", "package", "department", "provider" | |
| ] | |
| has_intent = any(word in q for word in intent_keywords) | |
| has_data = any(word in q for word in data_keywords) | |
| if has_data and not has_intent: | |
| return True | |
| return False | |
| class RobustHybridText2Code: | |
| def __init__(self, data_folder="data", model_dir="model/my_finetuned_model"): | |
| self.data = load_training_data(data_folder) | |
| self.retriever = EnhancedRetriever(self.data) | |
| self.generator = MultiModelGenerator( | |
| { | |
| "modelA": "model/my_finetuned_model", | |
| "modelB": "model/second_model_folder" | |
| } | |
| ) | |
| # self.generator = Generator(model_dir) | |
| all_cols = set() | |
| for item in self.data: | |
| code = item.get("pandas_code", "") | |
| cols = re.findall(r"df\[['\"]([^'\"]+)['\"]\]", code) | |
| all_cols.update(cols) | |
| self.col_map = {normalize_name(c): c for c in all_cols} | |
| def get_code(self, user_query): | |
| retrieved_results = self.retriever.retrieve_best_match(user_query, top_k=3) | |
| best = select_best_template(retrieved_results, user_query) | |
| print(f" [Best Match Similarity: {best['similarity']:.2f}]") | |
| print(f" Original Query: {best['query']}") | |
| if best["similarity"] > 0.95: | |
| print(" High similarity β using code directly.") | |
| code = best["pandas_code"] | |
| elif best["similarity"] >= 0.90: | |
| print(" Moderate similarity β adapting code.") | |
| code = enhanced_adaptation(user_query, best["pandas_code"], best["query"]) | |
| else: | |
| print(" Low similarity β generating new code.") | |
| #code = self.generator.generate(user_query) | |
| generated, used_model = self.generator.generate(user_query) | |
| print(f"[INFO] Model used for this query β {used_model}") | |
| code = generated | |
| return post_process_code(code, user_query) | |
| # class MultiDatasetHybridText2Code: | |
| # def __init__(self): | |
| # print(" Initializing Multi-Dataset Hybrid System with CSV Execution and Clarification Memory...\n") | |
| # self.datasets = { | |
| # "bill": {"folder": "data/bill_data", "csv_path": "data/bill_data/bill_dataset.csv"}, | |
| # "status": {"folder": "data/status_data", "csv_path": "data/status_data/dataset.csv"}, | |
| # "history": {"folder": "data/history_data", "csv_path": "data/history_data/status_history_dataset.csv"} | |
| # } | |
| # self.models = {} | |
| # for name, meta in self.datasets.items(): | |
| # print(f" Loading dataset: {name}") | |
| # self.models[name] = RobustHybridText2Code( | |
| # data_folder=meta["folder"], | |
| # model_dir="model/my_finetuned_model" ) | |
| # if os.path.exists(meta["csv_path"]): | |
| # df = pd.read_csv(meta["csv_path"]) | |
| # self.datasets[name]["df"] = df | |
| # print(f" Loaded {len(df)} records for {name} dataset.") | |
| # else: | |
| # print(f" CSV not found for {name}: {meta['csv_path']}") | |
| # print("\n Models and CSVs loaded successfully!\n") | |
| # self.routing_model = SentenceTransformer("all-MiniLM-L6-v2") | |
| # self.dataset_embeddings = {} | |
| # for name in self.models: | |
| # all_queries = [e.get("english") or e.get("query") for e in self.models[name].data] | |
| # mean_emb = self.routing_model.encode(all_queries, convert_to_tensor=True).mean(dim=0) | |
| # self.dataset_embeddings[name] = mean_emb | |
| # def detect_dataset(self, user_query): | |
| # q = user_query.lower().strip() | |
| # if any(word in q for word in ["bill", "billing", "bill details", "bill status","invoice"]): | |
| # print(" Rule-based routing: 'bill' detected β Using BILL dataset.") | |
| # return "bill" | |
| # elif any(word in q for word in ["claim history", "history", "previous claims", "old claims"]): | |
| # print(" Rule-based routing: 'claim history' detected β Using HISTORY dataset.") | |
| # if "history" not in self.datasets: | |
| # print(" History dataset not found β falling back to default routing.") | |
| # else: | |
| # return "history" | |
| # else: | |
| # return "status" | |
| # user_emb = self.routing_model.encode(user_query, convert_to_tensor=True) | |
| # sims = {name: float(util.pytorch_cos_sim(user_emb, emb)) for name, emb in self.dataset_embeddings.items()} | |
| # best_match = max(sims, key=sims.get) | |
| # print(f" Dataset routing via embeddings: {sims}") | |
| # print(f"Fallback selected: {best_match}") | |
| # return best_match | |
| # def execute_code(self, code, df): | |
| # try: | |
| # local_env = {"df": df, "pd": pd} | |
| # result = eval(code, {"__builtins__": {}}, local_env) | |
| # return result | |
| # except Exception as e: | |
| # print(f" Error executing code: {e}") | |
| # return None | |
| # def get_code(self, user_query,api_mode=False): | |
| # if detect_vague_query(user_query): | |
| # print(" Please specify what you want β number of claims, total amount, or claim details?") | |
| # return None | |
| # dataset_name = self.detect_dataset(user_query) | |
| # print(f" Using dataset: {dataset_name}") | |
| # bot = self.models[dataset_name] | |
| # code = bot.get_code(user_query) | |
| # df = self.datasets[dataset_name].get("df") | |
| # if df is not None and code: | |
| # print(f"\n Suggested Pandas Code:\n{code}") | |
| # result = self.execute_code(code, df) | |
| # if result is not None: | |
| # print(f"\n Result:\n{result}") | |
| # log_interaction(user_query, code, result, dataset_name) | |
| # # if not api_mode: | |
| # # save_user_example(dataset_name, user_query, code,result) | |
| # return code,result | |
| class MultiModelGenerator: | |
| def __init__(self, model_dirs): | |
| self.model_dirs = { | |
| "modelA": "model/modelA_dir", | |
| "modelB": "model/modelB_dir" | |
| } | |
| self.models = {} | |
| self.tokenizers = {} | |
| for name, path in model_dirs.items(): | |
| try: | |
| tok = AutoTokenizer.from_pretrained(path) | |
| try: | |
| model = AutoModelForSeq2SeqLM.from_pretrained(path) | |
| except: | |
| from transformers import T5ForConditionalGeneration | |
| model = T5ForConditionalGeneration.from_pretrained(path) | |
| self.models[name] = model | |
| self.tokenizers[name] = tok | |
| print(f"[MultiModel] Loaded model: {name} from {path}") | |
| except Exception as e: | |
| print(f"[MultiModel] Failed loading {name}: {e}") | |
| self.router = SentenceTransformer("all-MiniLM-L6-v2") | |
| def pick_best_model(self, query): | |
| query_l = query.lower() | |
| # KEYWORD-BASED ROUTING RULES | |
| trigger_keywords = [ | |
| "settelement age", | |
| "outstanding age", | |
| "top", | |
| "claim age", | |
| "rank" | |
| ] | |
| for kw in trigger_keywords: | |
| if kw in query_l: | |
| print(f"[MultiModel] Keyword '{kw}' detected β Using Model 2") | |
| return "modelB" # your second model | |
| # Otherwise β ALWAYS use model 1 | |
| print("[MultiModel] Default routing β Using Model 1") | |
| return "modelA" | |
| def generate(self, query): | |
| print("\n============= MULTI-MODEL GENERATE =============") | |
| chosen = self.pick_best_model(query) | |
| model = self.models[chosen] | |
| tokenizer = self.tokenizers[chosen] | |
| inputs = tokenizer(query, return_tensors="pt") | |
| out = model.generate(**inputs, max_length=128) | |
| decoded = tokenizer.decode(out[0], skip_special_tokens=True) | |
| print(f"[MultiModel] Final Answer from {chosen} β {decoded}") | |
| return decoded, chosen | |
| class ClaimBoticsEngine: | |
| def __init__(self): | |
| print("\n=== Initializing Multi-Dataset + Multi-Model Hybrid Engine ===\n") | |
| # 1οΈβ£ DATASET SETUP | |
| self.datasets = { | |
| "bill": {"folder": "data/bill_data", "csv_path": "data/bill_data/bill_dataset.csv"}, | |
| "status": {"folder": "data/status_data", "csv_path": "data/status_data/dataset.csv"}, | |
| "history": {"folder": "data/history_data", "csv_path": "data/history_data/history_dataset.csv"} | |
| } | |
| self.models_by_dataset = {} | |
| for name, meta in self.datasets.items(): | |
| print(f"Loading dataset: {name}") | |
| # Load JSON training data for retrieval | |
| data_pairs = load_training_data(meta["folder"]) | |
| # Load CSV dataframe | |
| if os.path.exists(meta["csv_path"]): | |
| df = pd.read_csv(meta["csv_path"]) | |
| self.datasets[name]["df"] = df | |
| print(f"Loaded {len(df)} rows for dataset: {name}") | |
| else: | |
| self.datasets[name]["df"] = None | |
| print(f"CSV not found: {meta['csv_path']}") | |
| # Load retriever = trained JSON Q&A | |
| retriever = EnhancedRetriever(data_pairs) | |
| # Load two generation LLM models | |
| generator = MultiModelGenerator({ | |
| "modelA": "model/my_finetuned_model", | |
| "modelB": "model/my_second_model" | |
| }) | |
| # Store all dataset tools | |
| self.models_by_dataset[name] = { | |
| "retriever": retriever, | |
| "generator": generator, | |
| "training_data": data_pairs, | |
| } | |
| print("\nEngine fully loaded!\n") | |
| # 2οΈβ£ DATASET ROUTING (Bill / Status / History) | |
| def detect_dataset(self, user_query): | |
| q = user_query.lower() | |
| if any(x in q for x in ["bill", "billing", "invoice"]): | |
| print("Routing β BILL dataset") | |
| return "bill" | |
| if any(x in q for x in ["history", "older claims", "previous"]): | |
| print("Routing β HISTORY dataset") | |
| return "history" | |
| print("Routing β STATUS dataset") | |
| return "status" | |
| # 3οΈβ£ CODE EXECUTION | |
| def execute_code(self, code, df): | |
| try: | |
| local_env = {"df": df, "pd": pd} | |
| result = eval(code, {"__builtins__": {}}, local_env) | |
| return result | |
| except Exception as e: | |
| print("Execution error:", e) | |
| return None | |
| # 4οΈβ£ MAIN PIPELINE | |
| def process_query(self, user_query): | |
| # --- dataset routing --- | |
| dataset = self.detect_dataset(user_query) | |
| df = self.datasets[dataset]["df"] | |
| retriever = self.models_by_dataset[dataset]["retriever"] | |
| generator = self.models_by_dataset[dataset]["generator"] | |
| # --- retrieve top matches from JSON training files --- | |
| retrieved = retriever.retrieve_best_match(user_query, top_k=3) | |
| best = select_best_template(retrieved, user_query) | |
| print(f"Best similarity = {best['similarity']:.4f}") | |
| # --- use template if high similarity --- | |
| if best["similarity"] > 0.95: | |
| print("High similarity β using template") | |
| code = best["pandas_code"] | |
| # --- modify template if moderate similarity --- | |
| elif best["similarity"] >= 0.90: | |
| print("Medium similarity β adapting template") | |
| code = enhanced_adaptation(user_query, best["pandas_code"], best["query"]) | |
| # --- low similarity β LLM calls & multi-model selection --- | |
| else: | |
| print("Low similarity β generating via LLM (ModelA / ModelB)") | |
| code, used_model = generator.generate(user_query) | |
| print(f"LLM Model Used: {used_model}") | |
| # Final code cleanup | |
| code = post_process_code(code, user_query) | |
| # --- Execute Pandas Code --- | |
| result = None | |
| if df is not None: | |
| result = self.execute_code(code, df) | |
| # Log interaction | |
| log_interaction(user_query, code, result, dataset) | |
| return { | |
| "dataset": dataset, | |
| "code": code, | |
| "result": result | |
| } | |
| def log_interaction(query, code, result, dataset): | |
| os.makedirs("logs", exist_ok=True) | |
| log_path = "logs/interaction_log.jsonl" | |
| entry = { | |
| "timestamp": datetime.datetime.now().isoformat(), | |
| "query": query, | |
| "dataset": dataset, | |
| "code": code, | |
| "result_preview": str(result)[:300] | |
| } | |
| with open(log_path, "a", encoding="utf-8") as f: | |
| f.write(json.dumps(entry) + "\n") | |
| # def save_user_example(dataset, query, code,result): | |
| # os.makedirs(f"logs", exist_ok=True) | |
| # path = f"logs/new_user_data.jsonl" | |
| # new_entry = { | |
| # "timestamp": datetime.datetime.now().isoformat(), | |
| # "query": query, | |
| # "dataset": dataset, | |
| # "code": code, | |
| # "result_preview": str(result)[:300] | |
| # } | |
| # with open(path, "a", encoding="utf-8") as f: | |
| # f.write(json.dumps(new_entry) + "\n") | |
| # print(f" Saved new user example to {path}") | |
| if __name__ == "__main__": | |
| print("\nInitializing Hybrid Text-to-Pandas Bot...\n") | |
| bot = ClaimBoticsEngine() | |
| print("Chatbot ready! Type your queries below. Type 'exit' to quit.\n") | |
| while True: | |
| try: | |
| user_query = input("You: ").strip() | |
| if user_query.lower() in ["exit", "quit"]: | |
| print("Goodbye!") | |
| break | |
| if not user_query: | |
| continue | |
| code, result = bot.get_code(user_query) | |
| print("\nBot:") | |
| if code: | |
| print(f" Suggested Pandas Code:\n {code}") | |
| else: | |
| print(" Could not generate code. Please clarify your query.") | |
| if result is not None: | |
| print(f"\n Execution Result:\n {result}") | |
| print("\n" + "-"*50 + "\n") | |
| except KeyboardInterrupt: | |
| print("\nInterrupted. Exiting chatbot...") | |
| break | |
| except Exception as e: | |
| print(f"Error: {e}") | |
| continue | |