import json import random from functools import lru_cache from typing import List, Dict, Any, Optional from .config import QA_PATH, TOP_QUESTION_IDS @lru_cache(maxsize=1) def load_qa_data() -> List[Dict[str, Any]]: try: return json.loads(QA_PATH.read_text(encoding="utf-8")) except Exception: return [] def get_question_by_id(qid: int) -> Optional[Dict[str, Any]]: for item in load_qa_data(): if item.get("id") == qid: return item return None def get_questions_by_ids(ids: List[int]) -> List[Dict[str, Any]]: items = [] for qid in ids: item = get_question_by_id(qid) if item: items.append(item) return items def random_questions(limit: int = 10) -> List[Dict[str, Any]]: data = load_qa_data() if not data: return [] if limit >= len(data): return data.copy() return random.sample(data, limit) def search_questions(query: str, limit: int = 10) -> List[Dict[str, Any]]: """ 简易检索:包含关键词的优先返回,不足则随机补齐。 """ data = load_qa_data() if not query: return random_questions(limit) q_lower = query.lower() matched = [item for item in data if q_lower in item.get("question", "").lower()] # 去重 + 截断 seen = set() results = [] for item in matched: if item["id"] in seen: continue results.append(item) seen.add(item["id"]) if len(results) >= limit: break # 不足部分随机补齐 if len(results) < limit: remaining = [x for x in data if x["id"] not in seen] random.shuffle(remaining) results.extend(remaining[: limit - len(results)]) return results[:limit] def top_questions(): return get_questions_by_ids(TOP_QUESTION_IDS)