Spaces:
Sleeping
Sleeping
Fix regeneration to use Groq instead of mock, improve mock fallback
Browse files- Pipeline regeneration now calls Groq via regenerate_with_refinement()
instead of hardcoded _generate_mock()
- Mock generator improved: filters stop words, scores sentences by
meaningful keyword overlap, picks most relevant sentences first
- Fixes garbage responses like "rt Ratio falls below 0.6"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- core/pipeline.py +6 -4
- generation/generator.py +19 -14
core/pipeline.py
CHANGED
|
@@ -275,10 +275,12 @@ class VDHFPipeline:
|
|
| 275 |
use_strict_mode=True
|
| 276 |
)
|
| 277 |
|
| 278 |
-
# Regenerate response
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
|
|
|
|
|
|
| 282 |
)
|
| 283 |
|
| 284 |
# Re-extract claims
|
|
|
|
| 275 |
use_strict_mode=True
|
| 276 |
)
|
| 277 |
|
| 278 |
+
# Regenerate response using Groq (or mock fallback)
|
| 279 |
+
verified_evidence = "\n".join(self.firewall.decision_engine.get_verified_evidence(firewall_result))
|
| 280 |
+
current_response = self.generator.regenerate_with_refinement(
|
| 281 |
+
query=user_query,
|
| 282 |
+
verified_evidence=verified_evidence,
|
| 283 |
+
prompt_template=refined_prompt
|
| 284 |
)
|
| 285 |
|
| 286 |
# Re-extract claims
|
generation/generator.py
CHANGED
|
@@ -98,30 +98,35 @@ class ResponseGenerator:
|
|
| 98 |
|
| 99 |
def _generate_mock(self, query: str, context: str) -> str:
|
| 100 |
"""Generate a mock response for testing without API."""
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
|
|
|
| 104 |
|
| 105 |
-
query_words = set(query.lower().split())
|
| 106 |
|
|
|
|
|
|
|
|
|
|
| 107 |
for sentence in sentences:
|
| 108 |
-
|
| 109 |
-
if not sentence:
|
| 110 |
-
continue
|
| 111 |
-
|
| 112 |
-
sentence_words = set(sentence.lower().split())
|
| 113 |
overlap = query_words & sentence_words
|
|
|
|
|
|
|
| 114 |
|
| 115 |
-
|
| 116 |
-
|
| 117 |
|
| 118 |
-
if
|
| 119 |
-
|
|
|
|
| 120 |
if not response.endswith('.'):
|
| 121 |
response += '.'
|
| 122 |
return response
|
|
|
|
|
|
|
| 123 |
else:
|
| 124 |
-
return
|
| 125 |
|
| 126 |
def _generate_mock_from_prompt(self, prompt: str) -> str:
|
| 127 |
"""Extract a simple response from the prompt context."""
|
|
|
|
| 98 |
|
| 99 |
def _generate_mock(self, query: str, context: str) -> str:
|
| 100 |
"""Generate a mock response for testing without API."""
|
| 101 |
+
stop_words = {'the', 'a', 'an', 'is', 'are', 'was', 'were', 'be', 'been',
|
| 102 |
+
'what', 'how', 'who', 'which', 'where', 'when', 'why', 'do',
|
| 103 |
+
'does', 'did', 'to', 'of', 'in', 'for', 'on', 'with', 'at',
|
| 104 |
+
'by', 'from', 'and', 'or', 'but', 'if', 'it', 'this', 'that'}
|
| 105 |
|
| 106 |
+
query_words = set(query.lower().split()) - stop_words
|
| 107 |
|
| 108 |
+
# Split into sentences and score by meaningful word overlap
|
| 109 |
+
sentences = [s.strip() for s in context.split('.') if len(s.strip()) > 20]
|
| 110 |
+
scored = []
|
| 111 |
for sentence in sentences:
|
| 112 |
+
sentence_words = set(sentence.lower().split()) - stop_words
|
|
|
|
|
|
|
|
|
|
|
|
|
| 113 |
overlap = query_words & sentence_words
|
| 114 |
+
if overlap:
|
| 115 |
+
scored.append((len(overlap), sentence))
|
| 116 |
|
| 117 |
+
# Sort by relevance (most overlapping words first)
|
| 118 |
+
scored.sort(key=lambda x: x[0], reverse=True)
|
| 119 |
|
| 120 |
+
if scored:
|
| 121 |
+
best = [s for _, s in scored[:4]]
|
| 122 |
+
response = ". ".join(best)
|
| 123 |
if not response.endswith('.'):
|
| 124 |
response += '.'
|
| 125 |
return response
|
| 126 |
+
elif context:
|
| 127 |
+
return context[:500].rsplit('.', 1)[0] + '.'
|
| 128 |
else:
|
| 129 |
+
return "No relevant information found in the uploaded documents."
|
| 130 |
|
| 131 |
def _generate_mock_from_prompt(self, prompt: str) -> str:
|
| 132 |
"""Extract a simple response from the prompt context."""
|