(question: str, response_language: str = "zh")
| 4587 | user_id: str, |
| 4588 | session_id: str, |
| 4589 | question: str, |
| 4590 | persist_chat: bool, |
| 4591 | ) -> Dict[str, Any]: |
| 4592 | if persist_chat: |
| 4593 | _persist_chat_turn(user_id, session_id, question, result) |
| 4594 | elif session_id: |
| 4595 | result["session_id"] = session_id |
| 4596 | return result |
| 4597 | |
| 4598 | |
| 4599 | def _direct_answer_stream(question: str, response_language: str = "zh") -> Iterator[Dict[str, Any]]: |
| 4600 | started = time.time() |
| 4601 | language = _normalize_response_language(response_language) |
| 4602 | llm = build_llm_provider() |
| 4603 | llm_error = None |
| 4604 | text_parts: List[str] = [] |
| 4605 | meta = { |
| 4606 | "citations": [], |
| 4607 | "sources": [], |
| 4608 | "elapsed_ms": 0, |
| 4609 | "response_language": language, |
| 4610 | "token_usage": { |
| 4611 | "provider": getattr(llm, "name", "unknown"), |
| 4612 | "model": getattr(llm, "model", "unknown"), |
| 4613 | "prompt_tokens": 0, |
| 4614 | "completion_tokens": 0, |
| 4615 | "llm_error": None, |
| 4616 | }, |
| 4617 | "streaming": {"provider": getattr(llm, "name", "") != "mock", "transport": "sse"}, |
| 4618 | } |
| 4619 | yield {"event": "meta", "data": meta} |
| 4620 | if getattr(llm, "name", "") == "mock": |
| 4621 | text = ( |
| 4622 | "This question does not require the local Wiki. No usable LLM is configured, " |
| 4623 | "so the offline desktop app cannot generate a general answer right now. " |
| 4624 | "Use @ to select papers or switch to a Wiki scope for local-paper answers." |
| 4625 | if language == "en" |
| 4626 | else "这个问题不需要调用本地 Wiki。当前未配置可用 LLM,因此离线版无法生成通用回答;如需基于本地论文回答,请用 @ 选择论文或切换到 Wiki 范围。" |
| 4627 | ) |
| 4628 | for chunk in _text_chunks(text): |
| 4629 | text_parts.append(chunk) |
| 4630 | yield {"event": "chunk", "data": {"text": chunk}} |
| 4631 | else: |
| 4632 | try: |
| 4633 | for chunk in llm.stream_generate( |
| 4634 | question, |
| 4635 | system=_direct_answer_prompt(language), |
| 4636 | temperature=0.0, |
| 4637 | max_tokens=_direct_answer_max_tokens(), |
| 4638 | ): |
| 4639 | if not chunk: |
| 4640 | continue |
| 4641 | text_parts.append(chunk) |
| 4642 | yield {"event": "chunk", "data": {"text": chunk}} |
| 4643 | except Exception as exc: |
| 4644 | llm_error = str(exc) |
| 4645 | text = ( |
| 4646 | f"This was routed as a general question and does not need local Wiki citations, " |
no test coverage detected