feat(nordagpt): avatars in chat + anti-hallucination rule for companies
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
- NordaGPT icon (nordagpt-icon.svg) as AI avatar instead of "AI" text - User profile photo as avatar (falls back to initial letter) - CRITICAL: added strict rule to never hallucinate company names - Only mention companies that exist in the provided database Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cc78711e17
commit
0a7fe6389f
@ -1008,6 +1008,13 @@ ZASADY PERSONALIZACJI:
|
|||||||
- Na pytania "co wiesz o mnie?" / "kim jestem?" — wypisz powyższe dane + powiązania firmowe z bazy
|
- Na pytania "co wiesz o mnie?" / "kim jestem?" — wypisz powyższe dane + powiązania firmowe z bazy
|
||||||
- Uwzględniaj kontekst firmy użytkownika w odpowiedziach
|
- Uwzględniaj kontekst firmy użytkownika w odpowiedziach
|
||||||
- NIE ujawniaj danych technicznych (user_id, company_id, rola systemowa)
|
- NIE ujawniaj danych technicznych (user_id, company_id, rola systemowa)
|
||||||
|
|
||||||
|
KRYTYCZNA ZASADA DOTYCZĄCA FIRM:
|
||||||
|
- WYMIENIAJ WYŁĄCZNIE firmy, które znajdują się w dostarczonej bazie danych poniżej
|
||||||
|
- NIGDY nie wymyślaj, nie zgaduj ani nie halucynuj nazw firm
|
||||||
|
- Jeśli w bazie nie ma firmy pasującej do zapytania, powiedz wprost: "W bazie Izby nie znalazłem firmy o takim profilu"
|
||||||
|
- Każda wymieniona firma MUSI mieć link do profilu w formacie [Nazwa](/firma/slug)
|
||||||
|
- Jeśli nie masz pewności czy firma istnieje w bazie — NIE WYMIENIAJ JEJ
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Inject user memory (facts + conversation summaries) into prompt
|
# Inject user memory (facts + conversation summaries) into prompt
|
||||||
|
|||||||
@ -433,9 +433,22 @@
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.message.assistant .message-avatar img {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
filter: brightness(0) invert(1);
|
||||||
|
}
|
||||||
|
|
||||||
.message.user .message-avatar {
|
.message.user .message-avatar {
|
||||||
background: var(--primary);
|
background: var(--primary);
|
||||||
color: white;
|
color: white;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message.user .message-avatar img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-content {
|
.message-content {
|
||||||
@ -1828,7 +1841,7 @@
|
|||||||
|
|
||||||
<!-- Typing indicator -->
|
<!-- Typing indicator -->
|
||||||
<div class="message assistant" id="typingIndicator" style="display: none;">
|
<div class="message assistant" id="typingIndicator" style="display: none;">
|
||||||
<div class="message-avatar">AI</div>
|
<div class="message-avatar"><img src="{{ url_for('static', filename='img/nordagpt-icon.svg') }}" alt="AI"></div>
|
||||||
<div class="typing-indicator active">
|
<div class="typing-indicator active">
|
||||||
<div class="typing-dot"></div>
|
<div class="typing-dot"></div>
|
||||||
<div class="typing-dot"></div>
|
<div class="typing-dot"></div>
|
||||||
@ -1861,6 +1874,12 @@
|
|||||||
{% block extra_js %}
|
{% block extra_js %}
|
||||||
// NordaGPT Chat - State
|
// NordaGPT Chat - State
|
||||||
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content || '';
|
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.content || '';
|
||||||
|
const AI_AVATAR_HTML = '<img src="{{ url_for("static", filename="img/nordagpt-icon.svg") }}" alt="AI">';
|
||||||
|
{% if current_user and current_user.avatar_path %}
|
||||||
|
const USER_AVATAR_HTML = '<img src="{{ url_for("static", filename=current_user.avatar_path) }}" alt="{{ current_user.name[:1] }}">';
|
||||||
|
{% else %}
|
||||||
|
const USER_AVATAR_HTML = '{{ current_user.name[:1].upper() if current_user else "U" }}';
|
||||||
|
{% endif %}
|
||||||
let currentConversationId = null;
|
let currentConversationId = null;
|
||||||
let conversations = [];
|
let conversations = [];
|
||||||
let currentModel = 'flash'; // Default model (Gemini 3 Flash - thinking mode, 10K RPD)
|
let currentModel = 'flash'; // Default model (Gemini 3 Flash - thinking mode, 10K RPD)
|
||||||
@ -2291,7 +2310,7 @@ async function loadConversation(conversationId) {
|
|||||||
|
|
||||||
// Clear messages and show loading
|
// Clear messages and show loading
|
||||||
const messagesDiv = document.getElementById('chatMessages');
|
const messagesDiv = document.getElementById('chatMessages');
|
||||||
messagesDiv.innerHTML = '<div class="message assistant"><div class="message-avatar">AI</div><div class="message-content">Ładowanie historii...</div></div>';
|
messagesDiv.innerHTML = '<div class="message assistant"><div class="message-avatar"><img src="{{ url_for('static', filename='img/nordagpt-icon.svg') }}" alt="AI"></div><div class="message-content">Ładowanie historii...</div></div>';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/api/chat/${conversationId}/history`);
|
const response = await fetch(`/api/chat/${conversationId}/history`);
|
||||||
@ -2305,7 +2324,7 @@ async function loadConversation(conversationId) {
|
|||||||
// Re-add typing indicator at the end
|
// Re-add typing indicator at the end
|
||||||
messagesDiv.innerHTML += `
|
messagesDiv.innerHTML += `
|
||||||
<div class="message assistant" id="typingIndicator" style="display: none;">
|
<div class="message assistant" id="typingIndicator" style="display: none;">
|
||||||
<div class="message-avatar">AI</div>
|
<div class="message-avatar"><img src="{{ url_for('static', filename='img/nordagpt-icon.svg') }}" alt="AI"></div>
|
||||||
<div class="typing-indicator active">
|
<div class="typing-indicator active">
|
||||||
<div class="typing-dot"></div>
|
<div class="typing-dot"></div>
|
||||||
<div class="typing-dot"></div>
|
<div class="typing-dot"></div>
|
||||||
@ -2317,7 +2336,7 @@ async function loadConversation(conversationId) {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading conversation:', error);
|
console.error('Error loading conversation:', error);
|
||||||
messagesDiv.innerHTML = '<div class="message assistant"><div class="message-avatar">AI</div><div class="message-content">Nie udało się załadować rozmowy.</div></div>';
|
messagesDiv.innerHTML = '<div class="message assistant"><div class="message-avatar"><img src="{{ url_for('static', filename='img/nordagpt-icon.svg') }}" alt="AI"></div><div class="message-content">Nie udało się załadować rozmowy.</div></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close mobile sidebar
|
// Close mobile sidebar
|
||||||
@ -2348,7 +2367,7 @@ function startNewConversation() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="message assistant" id="typingIndicator" style="display: none;">
|
<div class="message assistant" id="typingIndicator" style="display: none;">
|
||||||
<div class="message-avatar">AI</div>
|
<div class="message-avatar"><img src="{{ url_for('static', filename='img/nordagpt-icon.svg') }}" alt="AI"></div>
|
||||||
<div class="typing-indicator active">
|
<div class="typing-indicator active">
|
||||||
<div class="typing-dot"></div>
|
<div class="typing-dot"></div>
|
||||||
<div class="typing-dot"></div>
|
<div class="typing-dot"></div>
|
||||||
@ -2435,7 +2454,7 @@ async function sendMessage() {
|
|||||||
streamMsgDiv.className = 'message assistant';
|
streamMsgDiv.className = 'message assistant';
|
||||||
const streamAvatar = document.createElement('div');
|
const streamAvatar = document.createElement('div');
|
||||||
streamAvatar.className = 'message-avatar';
|
streamAvatar.className = 'message-avatar';
|
||||||
streamAvatar.textContent = 'AI';
|
streamAvatar.innerHTML = AI_AVATAR_HTML;
|
||||||
const streamContent = document.createElement('div');
|
const streamContent = document.createElement('div');
|
||||||
streamContent.className = 'message-content';
|
streamContent.className = 'message-content';
|
||||||
|
|
||||||
@ -2608,7 +2627,7 @@ function addMessage(role, content, animate = true, techInfo = null) {
|
|||||||
|
|
||||||
const avatar = document.createElement('div');
|
const avatar = document.createElement('div');
|
||||||
avatar.className = 'message-avatar';
|
avatar.className = 'message-avatar';
|
||||||
avatar.textContent = role === 'assistant' ? 'AI' : '{{ current_user.name[:1].upper() if current_user else "U" }}';
|
avatar.innerHTML = role === 'assistant' ? AI_AVATAR_HTML : USER_AVATAR_HTML;
|
||||||
|
|
||||||
const contentDiv = document.createElement('div');
|
const contentDiv = document.createElement('div');
|
||||||
contentDiv.className = 'message-content';
|
contentDiv.className = 'message-content';
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user