Update response_generator.py
Browse files- response_generator.py +4 -21
response_generator.py
CHANGED
|
@@ -30,31 +30,24 @@ class ResponseGenerator:
|
|
| 30 |
"""
|
| 31 |
Smart extraction with sentence selection
|
| 32 |
"""
|
| 33 |
-
# Get top chunks
|
| 34 |
top_chunks = relevant_docs.head(3)
|
| 35 |
|
| 36 |
-
# Extract query keywords
|
| 37 |
query_keywords = self._extract_keywords(query)
|
| 38 |
|
| 39 |
-
# Find best sentences
|
| 40 |
best_sentences = []
|
| 41 |
|
| 42 |
for idx, row in top_chunks.iterrows():
|
| 43 |
content = row['content']
|
| 44 |
similarity = row.get('similarity_score', 0)
|
| 45 |
|
| 46 |
-
# Split into sentences
|
| 47 |
sentences = self._split_sentences(content)
|
| 48 |
|
| 49 |
-
# Score each sentence
|
| 50 |
for sentence in sentences:
|
| 51 |
-
if len(sentence.strip()) < 20:
|
| 52 |
continue
|
| 53 |
|
| 54 |
-
# Calculate sentence score
|
| 55 |
score = similarity
|
| 56 |
|
| 57 |
-
# Boost if contains query keywords
|
| 58 |
sentence_lower = sentence.lower()
|
| 59 |
for keyword in query_keywords:
|
| 60 |
if keyword in sentence_lower:
|
|
@@ -66,17 +59,13 @@ class ResponseGenerator:
|
|
| 66 |
'chunk_id': idx
|
| 67 |
})
|
| 68 |
|
| 69 |
-
# Sort by score
|
| 70 |
best_sentences.sort(key=lambda x: x['score'], reverse=True)
|
| 71 |
|
| 72 |
-
# Take top 3 sentences
|
| 73 |
top_sentences = best_sentences[:3]
|
| 74 |
|
| 75 |
-
# Format answer
|
| 76 |
if not top_sentences:
|
| 77 |
return self._format_simple_answer(top_chunks)
|
| 78 |
|
| 79 |
-
# Build answer
|
| 80 |
answer_parts = ["**الإجابة:**\n"]
|
| 81 |
|
| 82 |
for i, sent in enumerate(top_sentences, 1):
|
|
@@ -85,7 +74,6 @@ class ResponseGenerator:
|
|
| 85 |
else:
|
| 86 |
answer_parts.append(f"\n{sent['text']}")
|
| 87 |
|
| 88 |
-
# Add metadata
|
| 89 |
answer_parts.append("\n\n---")
|
| 90 |
|
| 91 |
scores = top_chunks['similarity_score'].values if 'similarity_score' in top_chunks.columns else []
|
|
@@ -100,10 +88,8 @@ class ResponseGenerator:
|
|
| 100 |
"""
|
| 101 |
Extract meaningful keywords from query
|
| 102 |
"""
|
| 103 |
-
# Remove stop words
|
| 104 |
stop_words = {'ما', 'هي', 'هو', 'في', 'من', 'إلى', 'على', 'عن', 'ال', 'و', 'أو'}
|
| 105 |
|
| 106 |
-
# Split and clean
|
| 107 |
words = query.lower().split()
|
| 108 |
keywords = [w for w in words if len(w) > 2 and w not in stop_words]
|
| 109 |
|
|
@@ -113,7 +99,6 @@ class ResponseGenerator:
|
|
| 113 |
"""
|
| 114 |
Split text into sentences
|
| 115 |
"""
|
| 116 |
-
# Split by Arabic and English punctuation
|
| 117 |
sentences = re.split(r'[.؟!]\s+', text)
|
| 118 |
return [s.strip() for s in sentences if s.strip()]
|
| 119 |
|
|
@@ -124,10 +109,8 @@ class ResponseGenerator:
|
|
| 124 |
best_chunk = top_chunks.iloc[0]
|
| 125 |
content = best_chunk['content']
|
| 126 |
|
| 127 |
-
# Truncate if too long
|
| 128 |
if len(content) > 400:
|
| 129 |
content = content[:400]
|
| 130 |
-
# Try to end at sentence
|
| 131 |
last_period = max(content.rfind('.'), content.rfind('؟'), content.rfind('!'))
|
| 132 |
if last_period > 100:
|
| 133 |
content = content[:last_period + 1]
|
|
@@ -136,6 +119,6 @@ class ResponseGenerator:
|
|
| 136 |
|
| 137 |
score = best_chunk.get('similarity_score', 0)
|
| 138 |
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
|
|
|
| 30 |
"""
|
| 31 |
Smart extraction with sentence selection
|
| 32 |
"""
|
|
|
|
| 33 |
top_chunks = relevant_docs.head(3)
|
| 34 |
|
|
|
|
| 35 |
query_keywords = self._extract_keywords(query)
|
| 36 |
|
|
|
|
| 37 |
best_sentences = []
|
| 38 |
|
| 39 |
for idx, row in top_chunks.iterrows():
|
| 40 |
content = row['content']
|
| 41 |
similarity = row.get('similarity_score', 0)
|
| 42 |
|
|
|
|
| 43 |
sentences = self._split_sentences(content)
|
| 44 |
|
|
|
|
| 45 |
for sentence in sentences:
|
| 46 |
+
if len(sentence.strip()) < 20:
|
| 47 |
continue
|
| 48 |
|
|
|
|
| 49 |
score = similarity
|
| 50 |
|
|
|
|
| 51 |
sentence_lower = sentence.lower()
|
| 52 |
for keyword in query_keywords:
|
| 53 |
if keyword in sentence_lower:
|
|
|
|
| 59 |
'chunk_id': idx
|
| 60 |
})
|
| 61 |
|
|
|
|
| 62 |
best_sentences.sort(key=lambda x: x['score'], reverse=True)
|
| 63 |
|
|
|
|
| 64 |
top_sentences = best_sentences[:3]
|
| 65 |
|
|
|
|
| 66 |
if not top_sentences:
|
| 67 |
return self._format_simple_answer(top_chunks)
|
| 68 |
|
|
|
|
| 69 |
answer_parts = ["**الإجابة:**\n"]
|
| 70 |
|
| 71 |
for i, sent in enumerate(top_sentences, 1):
|
|
|
|
| 74 |
else:
|
| 75 |
answer_parts.append(f"\n{sent['text']}")
|
| 76 |
|
|
|
|
| 77 |
answer_parts.append("\n\n---")
|
| 78 |
|
| 79 |
scores = top_chunks['similarity_score'].values if 'similarity_score' in top_chunks.columns else []
|
|
|
|
| 88 |
"""
|
| 89 |
Extract meaningful keywords from query
|
| 90 |
"""
|
|
|
|
| 91 |
stop_words = {'ما', 'هي', 'هو', 'في', 'من', 'إلى', 'على', 'عن', 'ال', 'و', 'أو'}
|
| 92 |
|
|
|
|
| 93 |
words = query.lower().split()
|
| 94 |
keywords = [w for w in words if len(w) > 2 and w not in stop_words]
|
| 95 |
|
|
|
|
| 99 |
"""
|
| 100 |
Split text into sentences
|
| 101 |
"""
|
|
|
|
| 102 |
sentences = re.split(r'[.؟!]\s+', text)
|
| 103 |
return [s.strip() for s in sentences if s.strip()]
|
| 104 |
|
|
|
|
| 109 |
best_chunk = top_chunks.iloc[0]
|
| 110 |
content = best_chunk['content']
|
| 111 |
|
|
|
|
| 112 |
if len(content) > 400:
|
| 113 |
content = content[:400]
|
|
|
|
| 114 |
last_period = max(content.rfind('.'), content.rfind('؟'), content.rfind('!'))
|
| 115 |
if last_period > 100:
|
| 116 |
content = content[:last_period + 1]
|
|
|
|
| 119 |
|
| 120 |
score = best_chunk.get('similarity_score', 0)
|
| 121 |
|
| 122 |
+
answer = f"**الإجابة:**\n\n{content}\n\n---\n**دقة المطابقة:** {score:.0%}"
|
| 123 |
+
|
| 124 |
+
return answer
|