feat(nordagpt): integrate company_matcher — AI sees only matched companies, eliminates hallucinations
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
da7fc02070
commit
929e0b919f
@ -87,6 +87,14 @@ except ImportError:
|
||||
SMART_ROUTER_AVAILABLE = False
|
||||
logger.warning("Smart Router or Context Builder not available - using full context fallback")
|
||||
|
||||
# Import company matcher for pre-selecting relevant companies (eliminates hallucinations)
|
||||
try:
|
||||
from company_matcher import match_companies
|
||||
COMPANY_MATCHER_AVAILABLE = True
|
||||
except ImportError:
|
||||
COMPANY_MATCHER_AVAILABLE = False
|
||||
logger.warning("Company matcher not available - using full company list")
|
||||
|
||||
# Import memory service for user fact storage and prompt injection
|
||||
try:
|
||||
from memory_service import format_memory_for_prompt, extract_facts_async, summarize_conversation_async
|
||||
@ -449,6 +457,16 @@ class NordaBizChatEngine:
|
||||
context = self._build_conversation_context(db, conversation, user_message)
|
||||
effective_thinking = thinking_level
|
||||
|
||||
# Company Matcher — replace full company list with matched subset
|
||||
if COMPANY_MATCHER_AVAILABLE:
|
||||
try:
|
||||
matched = match_companies(user_message, user_context=user_context, max_results=15)
|
||||
context['matched_companies'] = matched
|
||||
context['all_companies'] = [] # Clear full list — use matched only
|
||||
logger.info(f"Company matcher found {len(matched)} companies for query")
|
||||
except Exception as e:
|
||||
logger.warning(f"Company matcher failed: {e}, using full company list")
|
||||
|
||||
# Get AI response with cost tracking
|
||||
response = self._query_ai(
|
||||
context,
|
||||
@ -1450,9 +1468,41 @@ W dyskusji [Artur Wiertel](link) pytał o moderację. Pełna treść: [moje uwag
|
||||
import logging
|
||||
logging.getLogger(__name__).warning(f"Feedback learning error: {e}")
|
||||
|
||||
# Add ALL companies in compact JSON format
|
||||
if context.get('all_companies'):
|
||||
# Build explicit whitelist of allowed company names + slugs
|
||||
# Add companies to prompt — matched (preferred) or full list (fallback)
|
||||
matched = context.get('matched_companies', [])
|
||||
if matched:
|
||||
system_prompt += "\n\n🏢 FIRMY Z BAZY IZBY PASUJĄCE DO ZAPYTANIA:\n"
|
||||
system_prompt += "Poniżej znajdują się JEDYNE firmy, które możesz wymienić w odpowiedzi.\n"
|
||||
system_prompt += "NIE WOLNO Ci wymyślać ani dodawać ŻADNYCH innych firm.\n"
|
||||
system_prompt += "Każdą firmę podawaj jako link: [Nazwa Firmy](/company/slug)\n\n"
|
||||
for c in matched:
|
||||
system_prompt += f"### {c['name']} → [link](/company/{c['slug']})\n"
|
||||
if c.get('category'):
|
||||
system_prompt += f"Kategoria: {c['category']}\n"
|
||||
if c.get('description'):
|
||||
system_prompt += f"Opis: {c['description'][:400]}\n"
|
||||
if c.get('services'):
|
||||
system_prompt += f"Usługi: {c['services'][:300]}\n"
|
||||
if c.get('structured_services'):
|
||||
system_prompt += f"Oferta: {', '.join(c['structured_services'][:10])}\n"
|
||||
if c.get('ai_insights'):
|
||||
ins = c['ai_insights']
|
||||
if ins.get('services_list'):
|
||||
system_prompt += f"Specjalizacje: {', '.join(ins['services_list'][:8])}\n"
|
||||
if ins.get('unique_selling_points'):
|
||||
system_prompt += f"Wyróżniki: {', '.join(ins['unique_selling_points'][:5])}\n"
|
||||
if c.get('google_rating') and c.get('google_reviews'):
|
||||
system_prompt += f"Google: {c['google_rating']}/5 ({c['google_reviews']} opinii)\n"
|
||||
if c.get('phone'):
|
||||
system_prompt += f"Tel: {c['phone']}\n"
|
||||
if c.get('website'):
|
||||
system_prompt += f"WWW: {c['website']}\n"
|
||||
if c.get('match_reasons'):
|
||||
system_prompt += f"Dopasowanie: {', '.join(c['match_reasons'])}\n"
|
||||
system_prompt += "\n"
|
||||
system_prompt += f"POWYŻSZE {len(matched)} FIRM TO JEDYNE, KTÓRE MOŻESZ WYMIENIĆ.\n"
|
||||
elif context.get('all_companies'):
|
||||
# Fallback: old behavior with all companies (when company_matcher unavailable)
|
||||
whitelist_lines = []
|
||||
for c in context['all_companies']:
|
||||
name = c.get('name', '')
|
||||
@ -1773,6 +1823,16 @@ W dyskusji [Artur Wiertel](link) pytał o moderację. Pełna treść: [moje uwag
|
||||
else:
|
||||
context = self._build_conversation_context(db, conversation, user_message)
|
||||
|
||||
# Company Matcher — replace full company list with matched subset
|
||||
if COMPANY_MATCHER_AVAILABLE:
|
||||
try:
|
||||
matched = match_companies(user_message, user_context=user_context, max_results=15)
|
||||
context['matched_companies'] = matched
|
||||
context['all_companies'] = [] # Clear full list — use matched only
|
||||
logger.info(f"Company matcher (stream) found {len(matched)} companies for query")
|
||||
except Exception as e:
|
||||
logger.warning(f"Company matcher failed: {e}, using full company list")
|
||||
|
||||
# Build full prompt
|
||||
full_prompt = self._build_full_prompt(context, user_message, user_context, thinking_level)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user