feat(serve): distinguish search vs chat in query log via X-Source header (#127)
CI / Python lint (push) Has been cancelled
CI / Frontend build (push) Has been cancelled
CI / Tests (push) Has been cancelled
CI / Plugin validate (push) Has been cancelled
Deploy / deploy (push) Has been cancelled

This commit is contained in:
Yichuan Wang
2026-07-27 15:54:41 -07:00
committed by GitHub
parent d745db7b23
commit 7a3c3041bd
4 changed files with 7 additions and 6 deletions
+4 -3
View File
@@ -102,12 +102,13 @@ def _init_query_log():
_query_log_path = log_dir / "queries.jsonl"
def _log_query(req: "SearchRequest", request_id: str):
def _log_query(req: "SearchRequest", request_id: str, source: str | None = None):
if _query_log_path is None:
return
record = {
"ts": datetime.now(timezone.utc).isoformat(),
"request_id": request_id,
"source": source,
"queries": [q.text for q in req.queries],
"has_image": [q.image is not None for q in req.queries],
"n_docs": req.n_docs,
@@ -461,7 +462,7 @@ def _resolve_url(article_id: int) -> str:
@app.post("/search", response_model=SearchResponse)
async def search(req: SearchRequest):
async def search(req: SearchRequest, request: Request):
t0 = time.time()
# Encode queries
@@ -570,7 +571,7 @@ async def search(req: SearchRequest):
time.time() - t0,
)
_log_query(req, _request_id_ctx.get())
_log_query(req, _request_id_ctx.get(), request.headers.get("X-Source"))
return SearchResponse(results=results)
+1 -1
View File
@@ -98,7 +98,7 @@ function createTools(onEvent, uploadedImage) {
onEvent("searching", { query: label })
const resp = await fetch(`${SEARCH_URL}/search`, {
method: "POST",
headers: { "Content-Type": "application/json" },
headers: { "Content-Type": "application/json", "X-Source": "chat" },
body: JSON.stringify({ queries: [queryObj], n_docs: args.n_results ?? 5, articles_only: true }),
signal: AbortSignal.timeout(30000),
})
+1 -1
View File
@@ -99,7 +99,7 @@ function createTools(
const resp = await fetch(`${SEARCH_URL}/search`, {
method: "POST",
headers: { "Content-Type": "application/json" },
headers: { "Content-Type": "application/json", "X-Source": "chat" },
body: JSON.stringify({
queries: [queryObj],
n_docs: args.n_results ?? 5,
+1 -1
View File
@@ -14,7 +14,7 @@ async function fetchApi<T>(path: string, init?: RequestInit): Promise<T> {
export async function search(req: SearchRequest): Promise<SearchResponse> {
return fetchApi<SearchResponse>("/search", {
method: "POST",
headers: { "Content-Type": "application/json" },
headers: { "Content-Type": "application/json", "X-Source": "search" },
// NOTE: the visual grid intentionally does NOT set articles_only — the
// Portal/Featured-picture pages it would drop are often the most visually
// striking tiles (panoramas, paintings), which is the point of this view.