Asmitha-28 commited on
Commit
6f14c50
·
verified ·
1 Parent(s): 4f7eaa5

Upload src\historical_memory.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. src//historical_memory.py +128 -0
src//historical_memory.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import pandas as pd
3
+ from sklearn.feature_extraction.text import TfidfVectorizer
4
+ from sklearn.neighbors import NearestNeighbors
5
+ import logging
6
+ from typing import List, Dict
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+ class HistoricalMemoryLayer:
11
+ """
12
+ Historical Memory Layer using Retrieval-Augmented Generation (RAG) concepts.
13
+ Stores successfully resolved past tickets.
14
+ When a new ambiguous ticket arrives, it retrieves the K nearest historical tickets.
15
+ This can be used to dynamically boost confidence or suggest resolutions.
16
+ """
17
+ def __init__(self, data_path: str = None):
18
+ if data_path is None:
19
+ base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
20
+ data_path = os.path.join(base, 'data', 'processed', 'train.csv')
21
+
22
+ self.data_path = data_path
23
+ self.vectorizer = TfidfVectorizer(stop_words='english', max_features=5000)
24
+ self.nn_model = NearestNeighbors(n_neighbors=5, metric='cosine')
25
+ self.memory_df = None
26
+ self.is_ready = False
27
+
28
+ self._load_memory()
29
+
30
+ def _load_memory(self):
31
+ try:
32
+ if not os.path.exists(self.data_path):
33
+ logger.warning(f"[HistoricalMemory] Data file not found at {self.data_path}")
34
+ return
35
+
36
+ self.memory_df = pd.read_csv(self.data_path)
37
+
38
+ # Ensure required columns exist
39
+ if 'text' not in self.memory_df.columns or 'category' not in self.memory_df.columns:
40
+ logger.warning("[HistoricalMemory] Required columns ('text', 'category') missing.")
41
+ return
42
+
43
+ # Fit TF-IDF and Nearest Neighbors
44
+ logger.info(f"[HistoricalMemory] Indexing {len(self.memory_df)} historical tickets...")
45
+ X = self.vectorizer.fit_transform(self.memory_df['text'].fillna(''))
46
+ self.nn_model.fit(X)
47
+
48
+ self.is_ready = True
49
+ logger.info("[HistoricalMemory] Indexing complete.")
50
+
51
+ except Exception as e:
52
+ logger.error(f"[HistoricalMemory] Failed to load memory: {e}")
53
+
54
+ def retrieve_similar(self, query_text: str, k: int = 3) -> List[Dict]:
55
+ """
56
+ Retrieve top K similar historical tickets.
57
+ """
58
+ if not self.is_ready:
59
+ return []
60
+
61
+ # Vectorize query
62
+ X_query = self.vectorizer.transform([query_text])
63
+
64
+ # Search
65
+ distances, indices = self.nn_model.kneighbors(X_query, n_neighbors=k)
66
+
67
+ results = []
68
+ for dist, idx in zip(distances[0], indices[0]):
69
+ # Cosine distance to similarity score
70
+ similarity = 1.0 - dist
71
+ row = self.memory_df.iloc[idx]
72
+
73
+ results.append({
74
+ 'text': row['text'],
75
+ 'category': row['category'],
76
+ 'similarity': round(similarity, 4)
77
+ })
78
+
79
+ return results
80
+
81
+ def compute_historical_boost(self, query_text: str, candidate_category: str, k: int = 5) -> float:
82
+ """
83
+ Calculate a confidence boost if the most similar past tickets
84
+ were resolved in the same candidate category.
85
+ """
86
+ if not self.is_ready:
87
+ return 0.0
88
+
89
+ similar_tickets = self.retrieve_similar(query_text, k=k)
90
+ if not similar_tickets:
91
+ return 0.0
92
+
93
+ # Count how many of the top-k match the candidate category, weighted by similarity
94
+ boost = 0.0
95
+ total_weight = 0.0
96
+
97
+ for t in similar_tickets:
98
+ weight = t['similarity']
99
+ total_weight += weight
100
+ if t['category'] == candidate_category:
101
+ boost += weight
102
+
103
+ if total_weight == 0:
104
+ return 0.0
105
+
106
+ match_ratio = boost / total_weight
107
+
108
+ # Max boost is 0.15 (15%)
109
+ return round(match_ratio * 0.15, 4)
110
+
111
+ if __name__ == "__main__":
112
+ logging.basicConfig(level=logging.INFO)
113
+ memory = HistoricalMemoryLayer()
114
+
115
+ test_queries = [
116
+ "My invoice from last month is incorrect, please fix the billing.",
117
+ "The API keeps returning 500 errors since last Tuesday's update.",
118
+ "How do I add another user to our account?"
119
+ ]
120
+
121
+ for q in test_queries:
122
+ print(f"\nQuery: '{q}'")
123
+ results = memory.retrieve_similar(q, k=2)
124
+ for r in results:
125
+ print(f" -> [{r['category']}] (sim: {r['similarity']:.2f}) {r['text']}")
126
+
127
+ boost = memory.compute_historical_boost(q, "billing")
128
+ print(f"Historical boost for 'billing': +{boost}")