style: 简化文档卡片样式,优化布局间距
This commit is contained in:
+2
-2
@@ -63,10 +63,10 @@ def _extract_message(response) -> tuple[str, str]:
|
||||
async def call_ollama(
|
||||
prompt: str,
|
||||
*,
|
||||
system_prompt: str = None,
|
||||
system_prompt: str | None = None,
|
||||
tag: str = "default",
|
||||
temperature: float = 0.7,
|
||||
thinking: str = None,
|
||||
thinking: str | None = None,
|
||||
) -> dict:
|
||||
"""
|
||||
调用 Ollama API 并返回 content 和 thinking。
|
||||
|
||||
+16
-28
@@ -1,6 +1,5 @@
|
||||
import asyncio
|
||||
import base64
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
@@ -12,7 +11,7 @@ from typing import Optional
|
||||
|
||||
from fastapi import FastAPI, HTTPException, Request, Security, File, UploadFile
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.responses import JSONResponse, StreamingResponse, Response
|
||||
from fastapi.responses import JSONResponse, Response
|
||||
from fastapi.security import APIKeyHeader
|
||||
from pydantic import BaseModel
|
||||
|
||||
@@ -125,10 +124,6 @@ def _sanitize_converted_markdown(text: str) -> str:
|
||||
return value.strip()
|
||||
|
||||
|
||||
def _sse_payload(payload: dict) -> str:
|
||||
return f"data: {json.dumps(payload)}\n\n"
|
||||
|
||||
|
||||
def get_client_ip(request: Request) -> str:
|
||||
if request.client:
|
||||
return request.headers.get("X-Client-IP") or request.client.host
|
||||
@@ -186,11 +181,10 @@ async def create_completion(request: Request, req: CompletionRequest, api_key: s
|
||||
)
|
||||
)
|
||||
|
||||
async with ACTIVE_COMPLETIONS_LOCK:
|
||||
existing = ACTIVE_COMPLETIONS.get(request_id)
|
||||
if existing and not existing.done():
|
||||
existing.cancel()
|
||||
ACTIVE_COMPLETIONS[request_id] = inference_task
|
||||
existing = ACTIVE_COMPLETIONS.get(request_id)
|
||||
if existing and not existing.done():
|
||||
existing.cancel()
|
||||
ACTIVE_COMPLETIONS[request_id] = inference_task
|
||||
|
||||
result = await inference_task
|
||||
content = result["content"] or ""
|
||||
@@ -204,26 +198,17 @@ async def create_completion(request: Request, req: CompletionRequest, api_key: s
|
||||
_preview(content, 120),
|
||||
)
|
||||
|
||||
async def generate():
|
||||
yield _sse_payload({"content": content})
|
||||
yield _sse_payload({"done": True})
|
||||
|
||||
return StreamingResponse(generate(), media_type="text/event-stream")
|
||||
return JSONResponse(content={"content": content, "request_id": request_id})
|
||||
except asyncio.CancelledError:
|
||||
logger.info("[%s] /v1/completions cancelled request_id=%s", request_tag, request_id)
|
||||
|
||||
async def cancelled():
|
||||
yield _sse_payload({"cancelled": True, "request_id": request_id, "done": True})
|
||||
|
||||
return StreamingResponse(cancelled(), media_type="text/event-stream")
|
||||
return JSONResponse(content={"cancelled": True, "request_id": request_id}, status_code=499)
|
||||
except Exception as e:
|
||||
logger.exception("[%s] /v1/completions failed request_id=%s: %s", request_tag, request_id, e)
|
||||
return JSONResponse(content={"error": str(e)}, status_code=500)
|
||||
finally:
|
||||
async with ACTIVE_COMPLETIONS_LOCK:
|
||||
active = ACTIVE_COMPLETIONS.get(request_id)
|
||||
if active is not None and active is inference_task:
|
||||
ACTIVE_COMPLETIONS.pop(request_id, None)
|
||||
active = ACTIVE_COMPLETIONS.get(request_id)
|
||||
if active is not None and active is inference_task:
|
||||
ACTIVE_COMPLETIONS.pop(request_id, None)
|
||||
|
||||
|
||||
@app.post("/v1/completions/cancel")
|
||||
@@ -399,7 +384,10 @@ if __name__ == "__main__":
|
||||
uvicorn.run(app, host="0.0.0.0", port=8001)
|
||||
|
||||
|
||||
# TTS and ASR routes
|
||||
from tts_asr import register_tts_asr_routes
|
||||
register_tts_asr_routes(app)
|
||||
# TTS and ASR routes (lazy loaded to avoid heavy import on startup)
|
||||
def _register_tts_asr_routes():
|
||||
from tts_asr import register_tts_asr_routes
|
||||
register_tts_asr_routes(app)
|
||||
|
||||
_register_tts_asr_routes()
|
||||
|
||||
|
||||
+72
-71
@@ -1,6 +1,13 @@
|
||||
from datetime import datetime, timedelta, timezone
|
||||
import re
|
||||
from typing import Tuple
|
||||
from typing import Protocol, Tuple, runtime_checkable
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
class UserPreferences(Protocol):
|
||||
language: str
|
||||
currency: str
|
||||
timezone: str
|
||||
|
||||
|
||||
def _get_current_datetime(timezone_pref: str = "auto") -> str:
|
||||
@@ -214,113 +221,107 @@ def _canonical_language_id(language_id: str) -> str:
|
||||
return LANGUAGE_SYNONYMS.get(safe, safe)
|
||||
|
||||
|
||||
def _language_guidance(language_id: str) -> str:
|
||||
canonical = _canonical_language_id(language_id)
|
||||
if canonical == "markdown":
|
||||
return ""
|
||||
if canonical == "mermaid":
|
||||
return """
|
||||
_JS_LANGS = {"javascript", "typescript"}
|
||||
_CODE_LANGS = {"python", "go", "rust", "java", "kotlin", "swift", "ruby", "php", "lua", "c", "cpp", "csharp", "r", "matlab", "dart"}
|
||||
|
||||
_LANG_GUIDANCE = {
|
||||
"mermaid": """
|
||||
Language-specific guidance (mermaid):
|
||||
- Output valid Mermaid syntax only.
|
||||
- Prefer concise, syntactically correct diagram statements.
|
||||
- Avoid prose unless the user prompt explicitly requires it."""
|
||||
if canonical == "latex":
|
||||
return """
|
||||
- Avoid prose unless the user prompt explicitly requires it.""",
|
||||
"latex": """
|
||||
Language-specific guidance (latex):
|
||||
- Output LaTeX math content only when completing LaTeX.
|
||||
- If CURSOR_IN_FENCED_CODE_BLOCK=true and CURSOR_FENCE_LANGUAGE is latex/tex/katex:
|
||||
- Output raw LaTeX lines only.
|
||||
- Do not wrap with $ or $$."""
|
||||
if canonical == "json":
|
||||
return """
|
||||
- Do not wrap with $ or $$.""",
|
||||
"json": """
|
||||
Language-specific guidance (json):
|
||||
- Output strict JSON only (no comments, no trailing commas).
|
||||
- Ensure valid quotes and braces."""
|
||||
if canonical == "yaml":
|
||||
return """
|
||||
- Ensure valid quotes and braces.""",
|
||||
"yaml": """
|
||||
Language-specific guidance (yaml):
|
||||
- Output valid YAML only.
|
||||
- Use consistent indentation and avoid tabs."""
|
||||
if canonical == "toml":
|
||||
return """
|
||||
- Use consistent indentation and avoid tabs.""",
|
||||
"toml": """
|
||||
Language-specific guidance (toml):
|
||||
- Output valid TOML only.
|
||||
- Keep key types consistent."""
|
||||
if canonical == "ini":
|
||||
return """
|
||||
- Keep key types consistent.""",
|
||||
"ini": """
|
||||
Language-specific guidance (ini):
|
||||
- Output valid INI only.
|
||||
- Keep section headers and key=value pairs consistent."""
|
||||
if canonical == "sql":
|
||||
return """
|
||||
- Keep section headers and key=value pairs consistent.""",
|
||||
"sql": """
|
||||
Language-specific guidance (sql):
|
||||
- Output a single, valid SQL statement unless context requires multiple.
|
||||
- Prefer ANSI SQL when dialect is unclear."""
|
||||
if canonical == "bash":
|
||||
return """
|
||||
- Prefer ANSI SQL when dialect is unclear.""",
|
||||
"bash": """
|
||||
Language-specific guidance (bash):
|
||||
- Output POSIX-compatible shell when possible.
|
||||
- Avoid interactive prompts or destructive commands unless requested."""
|
||||
if canonical == "powershell":
|
||||
return """
|
||||
- Avoid interactive prompts or destructive commands unless requested.""",
|
||||
"powershell": """
|
||||
Language-specific guidance (powershell):
|
||||
- Output valid PowerShell commands.
|
||||
- Avoid destructive commands unless explicitly requested."""
|
||||
if canonical == "html":
|
||||
return """
|
||||
- Avoid destructive commands unless explicitly requested.""",
|
||||
"html": """
|
||||
Language-specific guidance (html):
|
||||
- Output valid HTML only.
|
||||
- Keep markup minimal and well-formed."""
|
||||
if canonical == "css":
|
||||
return """
|
||||
- Keep markup minimal and well-formed.""",
|
||||
"css": """
|
||||
Language-specific guidance (css):
|
||||
- Output valid CSS only.
|
||||
- Use concise, readable selectors."""
|
||||
if canonical == "diff":
|
||||
return """
|
||||
- Use concise, readable selectors.""",
|
||||
"diff": """
|
||||
Language-specific guidance (diff):
|
||||
- Output a unified diff only.
|
||||
- Ensure @@ hunk headers and +/- lines are consistent."""
|
||||
if canonical == "regex":
|
||||
return """
|
||||
- Ensure @@ hunk headers and +/- lines are consistent.""",
|
||||
"regex": """
|
||||
Language-specific guidance (regex):
|
||||
- Output the regex pattern only.
|
||||
- Avoid delimiters unless explicitly requested."""
|
||||
if canonical in {"javascript", "typescript"}:
|
||||
return f"""
|
||||
Language-specific guidance ({canonical}):
|
||||
- Output valid {canonical} code.
|
||||
- Prefer modern syntax and avoid prose unless comments are needed."""
|
||||
if canonical in {"python", "go", "rust", "java", "kotlin", "swift", "ruby", "php", "lua", "c", "cpp", "csharp", "r", "matlab", "dart"}:
|
||||
return f"""
|
||||
Language-specific guidance ({canonical}):
|
||||
- Output valid {canonical} code.
|
||||
- Avoid prose unless context clearly expects comments or docstrings."""
|
||||
if canonical == "text":
|
||||
return """
|
||||
- Avoid delimiters unless explicitly requested.""",
|
||||
"text": """
|
||||
Language-specific guidance (text):
|
||||
- Output plain text only.
|
||||
- Avoid markdown formatting unless explicitly asked."""
|
||||
if canonical == "xml":
|
||||
return """
|
||||
- Avoid markdown formatting unless explicitly asked.""",
|
||||
"xml": """
|
||||
Language-specific guidance (xml):
|
||||
- Output well-formed XML only.
|
||||
- Ensure matching tags and proper escaping."""
|
||||
if canonical == "dockerfile":
|
||||
return """
|
||||
- Ensure matching tags and proper escaping.""",
|
||||
"dockerfile": """
|
||||
Language-specific guidance (dockerfile):
|
||||
- Output valid Dockerfile instructions only.
|
||||
- Keep layers minimal and ordered logically."""
|
||||
if canonical == "makefile":
|
||||
return """
|
||||
- Keep layers minimal and ordered logically.""",
|
||||
"makefile": """
|
||||
Language-specific guidance (makefile):
|
||||
- Output valid Makefile syntax only.
|
||||
- Use tabs for recipe lines."""
|
||||
return f"""
|
||||
Language-specific guidance ({canonical}):
|
||||
- Output valid {canonical} code.
|
||||
- Use tabs for recipe lines.""",
|
||||
}
|
||||
|
||||
_GENERIC_CODE = """
|
||||
Language-specific guidance ({lang}):
|
||||
- Output valid {lang} code.
|
||||
- Avoid prose unless context clearly expects comments or docstrings."""
|
||||
|
||||
_JS_CODE = """
|
||||
Language-specific guidance ({lang}):
|
||||
- Output valid {lang} code.
|
||||
- Prefer modern syntax and avoid prose unless comments are needed."""
|
||||
|
||||
|
||||
def _language_guidance(language_id: str) -> str:
|
||||
canonical = _canonical_language_id(language_id)
|
||||
if canonical == "markdown":
|
||||
return ""
|
||||
guidance = _LANG_GUIDANCE.get(canonical)
|
||||
if guidance:
|
||||
return guidance
|
||||
if canonical in _JS_LANGS:
|
||||
return _JS_CODE.format(lang=canonical)
|
||||
if canonical in _CODE_LANGS:
|
||||
return _GENERIC_CODE.format(lang=canonical)
|
||||
return _GENERIC_CODE.format(lang=canonical)
|
||||
|
||||
|
||||
def build_inline_system_prompt(language_id: str = "markdown") -> str:
|
||||
safe_language_id = _canonical_language_id(language_id)
|
||||
@@ -520,7 +521,7 @@ def build_completion_prompts(
|
||||
language_id: str = "markdown",
|
||||
location: str = "",
|
||||
thinking_level: str = "low",
|
||||
preferences: object = None,
|
||||
preferences: UserPreferences | None = None,
|
||||
) -> Tuple[str, str]:
|
||||
safe_language_id = _canonical_language_id(language_id)
|
||||
recent_prefix, recent_suffix = _prepare_context(prefix, suffix)
|
||||
@@ -601,7 +602,7 @@ def build_prompt(
|
||||
language_id: str = "markdown",
|
||||
location: str = "",
|
||||
thinking_level: str = "low",
|
||||
preferences: object = None,
|
||||
preferences: UserPreferences | None = None,
|
||||
) -> str:
|
||||
"""
|
||||
Backward-compatible helper. Returns only the user prompt body.
|
||||
|
||||
+2
-1
@@ -197,8 +197,9 @@ class ASRResponse(BaseModel):
|
||||
|
||||
|
||||
def get_api_key(api_key: str):
|
||||
from backend.main import API_KEY
|
||||
import main
|
||||
|
||||
API_KEY = main.API_KEY
|
||||
if api_key != API_KEY:
|
||||
raise HTTPException(status_code=403, detail="API Key 无效")
|
||||
return api_key
|
||||
|
||||
Reference in New Issue
Block a user