Soften the tone of the docs and comments written today
This commit is contained in:
@@ -29,6 +29,28 @@ interface ChatPanelProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
// The client must never be the thing that gives up first.
|
||||
//
|
||||
// The backend's own per-request budget is 40s (`max_wall_clock_ms` in
|
||||
// `apps/ai-service/config.py`), and that budget is only checked *between*
|
||||
// model calls — `rag/budget.py` says so explicitly: it cannot cancel a boto3
|
||||
// call already in flight, which is separately bounded by `read_timeout=20`
|
||||
// in `adapters/bedrock_converse.py`. So the backend's real worst case is
|
||||
// ~40s + one in-flight call ≈ 60s, and anything below that truncates work
|
||||
// the server was still legitimately doing.
|
||||
//
|
||||
// Measured against production 2026-08-11 (n=8, sequential, one user):
|
||||
// 6.2 / 6.4 / 8.4 / 10.9 / 12.4 / 21.7 / 25.1 / 40.3 seconds. A 25s limit
|
||||
// cuts off 2 of those 8, including the 25.1s case, which had returned a
|
||||
// correct grounded answer with 2 citations.
|
||||
const REQUEST_TIMEOUT_MS = 65_000;
|
||||
|
||||
// A single spinner for a minute reads as a hang, so the wait is made
|
||||
// legible rather than merely longer. This is a stopgap for the real fix
|
||||
// (streaming verified claims as they land); it does not make the request
|
||||
// faster, it only stops it looking broken.
|
||||
const SLOW_REQUEST_NOTICE_MS = 15_000;
|
||||
|
||||
const STARTER_QUESTIONS = [
|
||||
{
|
||||
category: "Chỉ Định",
|
||||
@@ -65,6 +87,7 @@ export function ChatPanel({
|
||||
}: ChatPanelProps) {
|
||||
const { resolvedTheme } = useTheme();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [elapsedMs, setElapsedMs] = useState(0);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const messagesEndRef = useRef<HTMLDivElement>(null);
|
||||
const abortControllerRef = useRef<AbortController | null>(null);
|
||||
@@ -98,7 +121,12 @@ export function ChatPanel({
|
||||
abortControllerRef.current = new AbortController();
|
||||
const timeoutId = window.setTimeout(() => {
|
||||
abortControllerRef.current?.abort();
|
||||
}, 25_000);
|
||||
}, REQUEST_TIMEOUT_MS);
|
||||
setElapsedMs(0);
|
||||
const startedAt = Date.now();
|
||||
const tickId = window.setInterval(() => {
|
||||
setElapsedMs(Date.now() - startedAt);
|
||||
}, 1000);
|
||||
|
||||
try {
|
||||
const res = await fetch("/api/chat", {
|
||||
@@ -128,13 +156,19 @@ export function ChatPanel({
|
||||
setError(
|
||||
stopRequestedRef.current
|
||||
? "Đã dừng chờ trên giao diện. Tác vụ đang chạy có thể cần vài giây để kết thúc an toàn."
|
||||
: "Yêu cầu vượt quá 25 giây và đã được dừng. Vui lòng thử lại với câu hỏi cụ thể hơn."
|
||||
// Describes the timing cause rather than suggesting the
|
||||
// question needs rewording, which rephrasing would not fix.
|
||||
: `Hệ thống xử lý quá ${Math.round(
|
||||
REQUEST_TIMEOUT_MS / 1000
|
||||
)} giây nên đã dừng yêu cầu này. Vui lòng bấm gửi lại.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
setError("Không thể kết nối đến máy chủ AI Service. Vui lòng kiểm tra lại dịch vụ backend.");
|
||||
} finally {
|
||||
window.clearTimeout(timeoutId);
|
||||
window.clearInterval(tickId);
|
||||
setElapsedMs(0);
|
||||
setIsLoading(false);
|
||||
abortControllerRef.current = null;
|
||||
}
|
||||
@@ -363,8 +397,15 @@ export function ChatPanel({
|
||||
<Pill className="h-4 w-4 animate-spin" />
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs font-bold text-txt-primary">Đang truy xuất Dược thư QGVN 2018...</p>
|
||||
<p className="text-[0.68rem] text-txt-muted">Đang phân tích chuyên luận & xác thực Entailment</p>
|
||||
<p className="text-xs font-bold text-txt-primary">
|
||||
Đang truy xuất Dược thư QGVN 2018...
|
||||
{elapsedMs >= 1000 && ` ${Math.floor(elapsedMs / 1000)}s`}
|
||||
</p>
|
||||
<p className="text-[0.68rem] text-txt-muted">
|
||||
{elapsedMs >= SLOW_REQUEST_NOTICE_MS
|
||||
? "Câu hỏi tra cả mục nên cần thêm thời gian đối chiếu nguồn — vẫn đang xử lý."
|
||||
: "Đang phân tích chuyên luận & xác thực Entailment"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -186,7 +186,7 @@ export function Composer({
|
||||
value={value}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder="Nhập tên thuốc hoặc thuộc tính cần tra (Ví dụ: Liều dùng Paracetamol, Chống chỉ định Amoxicillin...)"
|
||||
placeholder="Nhập câu hỏi của bạn..."
|
||||
rows={2}
|
||||
className="w-full resize-none bg-transparent px-3 py-2 text-sm text-txt-primary placeholder:text-txt-muted focus:outline-none"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user