Fix ai-service Dockerfile: bake in drug_entities.json, override its path
This commit is contained in:
@@ -20,7 +20,7 @@ import { cn } from "@duoc-thu/ui";
|
||||
interface ChatPanelProps {
|
||||
sessionId: string;
|
||||
initialQuery?: string;
|
||||
onCitationClick?: (citation: Citation, index: number) => void;
|
||||
onCitationClick?: (citation: Citation, index: number, allCitations: Citation[]) => void;
|
||||
onCitationsLoaded?: (citations: Citation[]) => void;
|
||||
activeCitationIndex?: number | null;
|
||||
className?: string;
|
||||
@@ -63,6 +63,7 @@ export function ChatPanel({
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const abortControllerRef = useRef<AbortController | null>(null);
|
||||
const initialQuerySentRef = useRef<string | undefined>(undefined);
|
||||
|
||||
const scrollToBottom = () => {
|
||||
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
||||
@@ -132,7 +133,15 @@ export function ChatPanel({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (initialQuery) {
|
||||
// Guard against firing twice for the same query: React 18 Strict Mode
|
||||
// (dev only) runs this effect setup twice on mount, and with no guard
|
||||
// that sent every quick-prompt click as two identical live requests
|
||||
// (found live 2026-08-07: duplicate "Chỉ định & Tác dụng không mong
|
||||
// muốn của Aspirin" turns in the trace). The ref persists across the
|
||||
// Strict Mode replay, so the second invocation for the same
|
||||
// `initialQuery` is a no-op; a genuinely new query still sends once.
|
||||
if (initialQuery && initialQuerySentRef.current !== initialQuery) {
|
||||
initialQuerySentRef.current = initialQuery;
|
||||
handleSendMessage(initialQuery);
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@@ -291,15 +300,31 @@ export function ChatPanel({
|
||||
{messages.length === 0 ? (
|
||||
renderEmptyState()
|
||||
) : (
|
||||
messages.map((msg) => (
|
||||
<ChatBubble
|
||||
key={msg.id}
|
||||
message={msg}
|
||||
onCitationClick={(citation, idx) => onCitationClick?.(citation, idx)}
|
||||
activeCitationIndex={activeCitationIndex}
|
||||
onRetry={() => handleSendMessage(msg.content)}
|
||||
/>
|
||||
))
|
||||
messages.map((msg, msgIdx) => {
|
||||
// Retry must resend the ORIGINAL user question, not this
|
||||
// bubble's own text — for an assistant bubble, `msg.content` is
|
||||
// the answer/error text itself, so resending it fed the error
|
||||
// message back in as if it were the next question (found live
|
||||
// 2026-08-07: a trace row where the query text WAS literally
|
||||
// "Dịch vụ đang gặp sự cố tạm thời..."). Walk back to the
|
||||
// nearest preceding user turn instead.
|
||||
const retryQuery =
|
||||
msg.role === "assistant"
|
||||
? [...messages.slice(0, msgIdx)].reverse().find((m) => m.role === "user")?.content
|
||||
: undefined;
|
||||
return (
|
||||
<ChatBubble
|
||||
key={msg.id}
|
||||
message={msg}
|
||||
onCitationClick={(citation, idx, allCitations) =>
|
||||
onCitationClick?.(citation, idx, allCitations)
|
||||
}
|
||||
activeCitationIndex={activeCitationIndex}
|
||||
onRetry={retryQuery ? () => handleSendMessage(retryQuery) : undefined}
|
||||
onQuickReply={(text) => handleSendMessage(text)}
|
||||
/>
|
||||
);
|
||||
})
|
||||
)}
|
||||
|
||||
{/* Loading Indicator */}
|
||||
|
||||
Reference in New Issue
Block a user