Knowledge Chat: surface LangSmith trace link when tracing enabled (reads /rag/config)

This commit is contained in:
mo
2026-06-28 12:01:06 +00:00
parent 323acda6d4
commit 03f300d46b
@@ -40,6 +40,7 @@ export function KnowledgeChatView({ onGpuActivity }: Props = {}) {
const [catalogDocs, setCatalogDocs] = useState<number | null>(null) const [catalogDocs, setCatalogDocs] = useState<number | null>(null)
const [showArch, setShowArch] = useState(true) const [showArch, setShowArch] = useState(true)
const [activeStage, setActiveStage] = useState<number | null>(null) const [activeStage, setActiveStage] = useState<number | null>(null)
const [traceCfg, setTraceCfg] = useState<{ tracing: boolean; project: string; smith_url: string } | null>(null)
const bottomRef = useRef<HTMLDivElement>(null) const bottomRef = useRef<HTMLDivElement>(null)
const loadMeta = useCallback(async () => { const loadMeta = useCallback(async () => {
@@ -77,6 +78,13 @@ export function KnowledgeChatView({ onGpuActivity }: Props = {}) {
loadCatalog() loadCatalog()
}, [loadMeta, loadCatalog]) }, [loadMeta, loadCatalog])
useEffect(() => {
fetch('/rag/config')
.then((r) => (r.ok ? r.json() : null))
.then((c) => { if (c) setTraceCfg(c) })
.catch(() => {})
}, [])
useEffect(() => { useEffect(() => {
bottomRef.current?.scrollIntoView({ behavior: 'smooth' }) bottomRef.current?.scrollIntoView({ behavior: 'smooth' })
}, [messages, loading]) }, [messages, loading])
@@ -351,6 +359,17 @@ export function KnowledgeChatView({ onGpuActivity }: Props = {}) {
<StatusPill ok={health.llm} label="LLM" /> <StatusPill ok={health.llm} label="LLM" />
</> </>
)} )}
{traceCfg?.tracing && (
<a
href={traceCfg.smith_url}
target="_blank"
rel="noreferrer"
title={`LangSmith project: ${traceCfg.project}`}
className="inline-flex items-center gap-1 rounded border border-emerald-400/50 bg-emerald-500/15 px-2 py-1 text-[10px] font-medium text-emerald-300 hover:bg-emerald-500/25"
>
<Workflow className="h-3.5 w-3.5" /> LangSmith
</a>
)}
<button <button
type="button" type="button"
onClick={() => setShowArch((v) => !v)} onClick={() => setShowArch((v) => !v)}
@@ -369,7 +388,7 @@ export function KnowledgeChatView({ onGpuActivity }: Props = {}) {
{showArch && ( {showArch && (
<div className="shrink-0 border-b border-border bg-surface-overlay/20 px-4 py-3"> <div className="shrink-0 border-b border-border bg-surface-overlay/20 px-4 py-3">
<RagFlow loading={loading} ingesting={ingesting} activeStage={activeStage} /> <RagFlow loading={loading} ingesting={ingesting} activeStage={activeStage} smithUrl={traceCfg?.tracing ? traceCfg.smith_url : null} project={traceCfg?.project} />
</div> </div>
)} )}
@@ -565,7 +584,7 @@ const QUERY_STAGES = [
const STAGE_LABEL = ['Question', 'Embed', 'Retrieve', 'Context', 'LLM', 'Answer'] const STAGE_LABEL = ['Question', 'Embed', 'Retrieve', 'Context', 'LLM', 'Answer']
function RagFlow({ loading, ingesting, activeStage }: { loading: boolean; ingesting: boolean; activeStage: number | null }) { function RagFlow({ loading, ingesting, activeStage, smithUrl, project }: { loading: boolean; ingesting: boolean; activeStage: number | null; smithUrl?: string | null; project?: string }) {
return ( return (
<div className="space-y-2"> <div className="space-y-2">
<div className="flex flex-wrap items-center gap-2 text-[9px] font-semibold uppercase tracking-wider text-foreground-faint"> <div className="flex flex-wrap items-center gap-2 text-[9px] font-semibold uppercase tracking-wider text-foreground-faint">
@@ -574,6 +593,9 @@ function RagFlow({ loading, ingesting, activeStage }: { loading: boolean; ingest
<span className="h-1.5 w-1.5 rounded-full bg-emerald-400" /> orchestrated by LangChain <span className="h-1.5 w-1.5 rounded-full bg-emerald-400" /> orchestrated by LangChain
</span> </span>
<span className="rounded bg-docker/15 px-1.5 py-0.5 font-mono text-[8px] normal-case text-docker">ChromaDB · Docling · sentence-transformers</span> <span className="rounded bg-docker/15 px-1.5 py-0.5 font-mono text-[8px] normal-case text-docker">ChromaDB · Docling · sentence-transformers</span>
{smithUrl && (
<a href={smithUrl} target="_blank" rel="noreferrer" title={project ? `LangSmith project: ${project}` : 'LangSmith'} className="inline-flex items-center gap-1 rounded-md border border-emerald-400/40 bg-emerald-500/10 px-1.5 py-0.5 font-mono text-[8px] normal-case text-emerald-300 hover:bg-emerald-500/20">LangSmith traces </a>
)}
{activeStage != null && ( {activeStage != null && (
<span className="ml-auto flex items-center gap-1 normal-case text-docker"> <span className="ml-auto flex items-center gap-1 normal-case text-docker">
<span className="h-1.5 w-1.5 animate-ping rounded-full bg-docker" /> {STAGE_LABEL[activeStage] || 'working'} <span className="h-1.5 w-1.5 animate-ping rounded-full bg-docker" /> {STAGE_LABEL[activeStage] || 'working'}