Enhance SQL generation and streaming capabilities in the API server. Introduce optional parameters for streaming throttle and SQL stream granularity in NLChatRequest. Implement new functions for iterating SQL generation content pieces and adjusting streaming behavior based on user-defined settings. Update prompts for few-shot SQL adaptation and improve logging for SQL generation processes. Refactor orchestrator methods to support streaming responses and integrate few-shot SQL conditions. Update impact analysis documentation to reflect these changes.

This commit is contained in:
陈辅元
2026-04-16 13:48:44 +08:00
parent 695356a496
commit bff5f85d60
16 changed files with 586 additions and 103 deletions
+87 -1
View File
@@ -19,7 +19,7 @@ Few-shot示例选择器 - 基于经验数据集动态选择相关示例
import json
import os
from pathlib import Path
from typing import List, Dict, Optional
from typing import List, Dict, Optional, Tuple
from dataclasses import dataclass
import numpy as np
import logging
@@ -158,6 +158,92 @@ class FewShotSelector:
self.cache_path = None
logger.info("[OK] Few-shot 使用 Chroma(%s 条)", self._chroma_store.count())
@property
def is_chroma_backend(self) -> bool:
"""是否使用 Chroma 持久化库(`data/embeddings/chroma_fewshot` 等)。"""
return self._chroma_store is not None
def _passes_filters(
self,
sample: "ExperienceSample",
min_rating: Optional[int],
required_tags: Optional[List[str]],
max_difficulty: str,
exclude_qids: Optional[List[str]],
) -> bool:
if exclude_qids and sample.qid in exclude_qids:
return False
if min_rating and sample.rating is not None and sample.rating < min_rating:
return False
if max_difficulty == "easy" and sample.difficulty != "easy":
return False
if max_difficulty == "medium" and sample.difficulty == "hard":
return False
if required_tags and not all(tag in sample.tags for tag in required_tags):
return False
return True
def select_best_with_score(
self,
question: str,
min_rating: Optional[int] = None,
required_tags: Optional[List[str]] = None,
max_difficulty: str = "hard",
exclude_qids: Optional[List[str]] = None,
) -> Optional[Tuple[ExperienceSample, float]]:
"""
返回通过筛选的**相似度最高**一条样本及分数 ``[0,1]``(与向量余弦一致:1 - distance)。
无命中时返回 ``None``。
"""
if self._chroma_store is not None:
from utils.fewshot_chroma_store import sample_from_chroma_metadata
over_fetch = 96
rows = self._chroma_store.search_raw(question, top_k=over_fetch)
for score, meta, doc in rows:
s = sample_from_chroma_metadata(meta, doc)
if not self._passes_filters(
s, min_rating, required_tags, max_difficulty, exclude_qids
):
continue
logger.info(
"[Few-shot] best_with_score: qid=%s score=%.4f preview=%r",
s.qid,
float(score),
(s.question_zh or "")[:100],
)
return (s, float(score))
return None
if self._embedder is None or self.embeddings is None or len(self.samples) == 0:
return None
q_emb = self._embedder.encode(
[question],
batch_size=1,
normalize=True,
show_progress=False,
)[0]
scores = np.dot(self.embeddings, q_emb)
best: Optional[Tuple[float, ExperienceSample]] = None
for idx, (score, sample) in enumerate(zip(scores, self.samples)):
if not self._passes_filters(
sample, min_rating, required_tags, max_difficulty, exclude_qids
):
continue
s = float(score)
if best is None or s > best[0]:
best = (s, sample)
if best is None:
return None
logger.info(
"[Few-shot] best_with_score(numpy): qid=%s score=%.4f preview=%r",
best[1].qid,
best[0],
(best[1].question_zh or "")[:100],
)
return (best[1], best[0])
def _load_samples(self):
"""从 JSONL 加载样本到内存(非 Chroma 模式必需;Chroma 空库时用于首次灌库)。"""
if self.samples_path is None: