fix(nordagpt): empty matcher fallback, no-results prompt, hide costs for users, streaming timeout
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
1. When company_matcher returns [], keep full company list as fallback instead of leaving AI with zero data 2. Add explicit "no results" instruction in prompt to prevent hallucinated company names 3. Hide cost badge chip from non-admin users (IS_ADMIN gate) 4. Add 60s AbortController timeout on streaming fetch to prevent hung connections Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
50d31c1b84
commit
8ee998b42f
@ -461,8 +461,12 @@ class NordaBizChatEngine:
|
||||
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
|
||||
if matched: # Only use matcher results if non-empty
|
||||
context['matched_companies'] = matched
|
||||
context['all_companies'] = [] # Clear full list — use matched only
|
||||
else:
|
||||
logger.info("Company matcher returned 0 results — keeping full company list as fallback")
|
||||
# Don't clear all_companies — AI will use the full list
|
||||
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")
|
||||
@ -1517,6 +1521,10 @@ W dyskusji [Artur Wiertel](link) pytał o moderację. Pełna treść: [moje uwag
|
||||
system_prompt += "\n\n🏢 SZCZEGÓŁY FIRM:\n"
|
||||
system_prompt += json.dumps(context['all_companies'], ensure_ascii=False, indent=None)
|
||||
system_prompt += "\n"
|
||||
else:
|
||||
system_prompt += "\n\n⚠️ BRAK DOPASOWANYCH FIRM: Wyszukiwanie nie znalazło firm bezpośrednio pasujących do tego zapytania. "
|
||||
system_prompt += "Odpowiedz na pytanie ogólnie, bez wymieniania konkretnych nazw firm. "
|
||||
system_prompt += "NIE WYMYŚLAJ nazw firm. Jeśli pytanie dotyczy firm, powiedz: 'W bazie Izby nie znalazłem firmy o takim profilu.'\n"
|
||||
|
||||
# Add recommendations (peer endorsements)
|
||||
if context.get('recommendations'):
|
||||
@ -1829,8 +1837,12 @@ W dyskusji [Artur Wiertel](link) pytał o moderację. Pełna treść: [moje uwag
|
||||
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
|
||||
if matched: # Only use matcher results if non-empty
|
||||
context['matched_companies'] = matched
|
||||
context['all_companies'] = [] # Clear full list — use matched only
|
||||
else:
|
||||
logger.info("Company matcher (stream) returned 0 results — keeping full company list as fallback")
|
||||
# Don't clear all_companies — AI will use the full list
|
||||
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")
|
||||
|
||||
@ -1930,6 +1930,7 @@ let currentConversationId = null;
|
||||
let conversations = [];
|
||||
let currentModel = 'flash'; // Default model (Gemini 3 Flash - thinking mode, 10K RPD)
|
||||
let monthlyUsageCost = 0; // Koszt miesięczny użytkownika
|
||||
const IS_ADMIN = {{ 'true' if current_user.is_admin or current_user.can_access_admin_panel() else 'false' }};
|
||||
|
||||
// ============================================
|
||||
// Model Selection Toggle Functions
|
||||
@ -2525,11 +2526,14 @@ async function sendMessage() {
|
||||
|
||||
// Try streaming endpoint
|
||||
let streamingSucceeded = false;
|
||||
const abortController = new AbortController();
|
||||
const streamTimeout = setTimeout(() => abortController.abort(), 60000); // 60s timeout
|
||||
try {
|
||||
const streamResp = await fetch(`/api/chat/${currentConversationId}/message/stream`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrfToken },
|
||||
body: JSON.stringify({ message: message, model: currentModel })
|
||||
body: JSON.stringify({ message: message, model: currentModel }),
|
||||
signal: abortController.signal
|
||||
});
|
||||
|
||||
if (!streamResp.ok) throw new Error(`HTTP ${streamResp.status}`);
|
||||
@ -2596,7 +2600,7 @@ async function sendMessage() {
|
||||
let badgeHTML = `<span class="badge-chip model">${modelLabel}</span>`;
|
||||
if (cIcon && tLabel) badgeHTML += `<span class="badge-chip thinking">${cIcon} ${tLabel}</span>`;
|
||||
badgeHTML += `<span class="badge-chip time">⏱ ${latencySec}s</span>`;
|
||||
badgeHTML += `<span class="badge-chip cost">💰 ${costStr}</span>`;
|
||||
if (IS_ADMIN) badgeHTML += `<span class="badge-chip cost">💰 ${costStr}</span>`;
|
||||
infoBadge.innerHTML = badgeHTML;
|
||||
streamContent.appendChild(infoBadge);
|
||||
|
||||
@ -2623,7 +2627,9 @@ async function sendMessage() {
|
||||
}
|
||||
}
|
||||
}
|
||||
clearTimeout(streamTimeout);
|
||||
} catch (streamError) {
|
||||
clearTimeout(streamTimeout);
|
||||
console.warn('Streaming failed, falling back to non-streaming:', streamError);
|
||||
// Remove the partial streaming bubble
|
||||
streamMsgDiv.remove();
|
||||
@ -2718,7 +2724,7 @@ function addMessage(role, content, animate = true, techInfo = null) {
|
||||
// Build badge content with chips
|
||||
let badgeHTML = `<span class="badge-chip model">${modelLabel}</span>`;
|
||||
badgeHTML += `<span class="badge-chip time">⏱ ${latencySec}s</span>`;
|
||||
badgeHTML += `<span class="badge-chip cost">💰 ${costStr}</span>`;
|
||||
if (IS_ADMIN) badgeHTML += `<span class="badge-chip cost">💰 ${costStr}</span>`;
|
||||
|
||||
infoBadge.innerHTML = badgeHTML;
|
||||
contentDiv.appendChild(infoBadge);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user