File size: 2,680 Bytes
db764ae 9f87ec0 db764ae 9f87ec0 db764ae 9f87ec0 db764ae 9f87ec0 db764ae | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | import { useState } from "react";
import { api } from "../api";
import type { QueryResultItem } from "../types";
import { useApiCall } from "../hooks/useApiCall";
import ScoreBar from "./ScoreBar";
import StatusMessage from "./StatusMessage";
import DocumentViewer from "./DocumentViewer";
export default function SemanticSearch() {
const [query, setQuery] = useState("");
const [topK, setTopK] = useState(10);
const { data: results, loading, error, run } = useApiCall<QueryResultItem[]>();
async function handleSearch() {
if (!query.trim()) return;
await run(() => api.query({ text: query, top_k: topK }).then((r) => r.results));
}
return (
<div>
<div className="panel">
<h2>Semantic Search</h2>
<p className="panel-desc">
Find passages most semantically similar to your query across the entire corpus.
</p>
<div className="form-row">
<div className="form-group">
<label>Query</label>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="e.g. a place where children learn and take tests"
onKeyDown={(e) => e.key === "Enter" && handleSearch()}
/>
</div>
<div className="form-group form-group-sm">
<label>Top K</label>
<input type="number" value={topK} onChange={(e) => setTopK(+e.target.value)} min={1} max={50} />
</div>
<div className="form-group form-group-sm">
<label> </label>
<button className="btn btn-primary" onClick={handleSearch} disabled={loading || !query.trim()}>
{loading ? "Searching..." : "Search"}
</button>
</div>
</div>
</div>
{error && <StatusMessage type="err" message={error} />}
{results && (
<div className="panel">
<h3>Results ({results.length})</h3>
{results.map((r) => (
<DocumentViewer key={`${r.doc_id}-${r.chunk_index}`} docId={r.doc_id}>
<div className="result-card" style={{ cursor: "pointer" }}>
<div className="result-header">
<div>
<span className="badge">#{r.rank}</span>{" "}
<span className="badge">{r.doc_id}</span>{" "}
<span className="tag">chunk {r.chunk_index}</span>
</div>
<ScoreBar score={r.score} />
</div>
<div className="result-text">{r.text}</div>
</div>
</DocumentViewer>
))}
</div>
)}
</div>
);
}
|