various fixes
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
"""
|
||||
统一配置:所有环境变量通过此模块的 Settings 单点读取。
|
||||
业务代码只允许 import settings,禁止散落 os.getenv() / load_dotenv()。
|
||||
|
||||
本地开发时由 api/development.sh 在启动前将 .env.development 复制为 .env(若尚无 .env)。
|
||||
Docker / 服务端由镜像与 compose 注入进程环境;此处仅固定读取工作目录下的 .env 作为默认值来源。
|
||||
进程环境变量(容器 environment、export)覆盖 .env 同名项。
|
||||
"""
|
||||
|
||||
import secrets
|
||||
@@ -54,10 +58,9 @@ class Settings(BaseSettings):
|
||||
tencent_sms_template_id: str = ""
|
||||
tencent_sms_template_param_count: int = 2
|
||||
|
||||
# ── Tencent ASR ──────────────────────────────────────────
|
||||
# ── Tencent ASR / TTS(共用 Secret;与短信、COS 密钥独立)────────────────
|
||||
tencent_secret_id: str = ""
|
||||
tencent_secret_key: str = ""
|
||||
tencent_asr_app_id: str = ""
|
||||
|
||||
# ── TTS (openai | tencent),与 ASR 独立:仅控制回复侧语音合成 ──
|
||||
enable_tts: bool = True
|
||||
@@ -94,15 +97,11 @@ class Settings(BaseSettings):
|
||||
enable_test_subscription: int = 0
|
||||
enable_test_plan: str = "" # "1" / "true" / "yes" 为 True
|
||||
enable_docs: bool = True
|
||||
migration_database_url: str = "" # 脚本迁移用,空则用 database_url
|
||||
|
||||
# ── Memoir Image ─────────────────────────────────────────
|
||||
memoir_image_enabled: bool = False
|
||||
memoir_image_max_per_chapter: int = 2
|
||||
memoir_image_poll_interval: int = 3
|
||||
memoir_image_max_attempts: int = 20
|
||||
memoir_image_chars_per_extra: int = 1500
|
||||
memoir_image_max_cap: int = 8
|
||||
memoir_image_provider: str = "liblib"
|
||||
memoir_image_style_default: str = "watercolor"
|
||||
memoir_image_size_default: str = "1280x720"
|
||||
|
||||
@@ -5,9 +5,6 @@ if TYPE_CHECKING:
|
||||
from app.core.config import Settings
|
||||
|
||||
DEFAULT_LIBLIB_TEMPLATE_UUID = "5d7e67009b344550bc1aa6ccbfa1d7f4"
|
||||
DEFAULT_MAX_IMAGES_PER_CHAPTER = 2
|
||||
DEFAULT_CHARS_PER_EXTRA_IMAGE = 1500
|
||||
DEFAULT_MAX_IMAGES_CAP = 8
|
||||
DEFAULT_IMAGE_PROVIDER = "liblib"
|
||||
DEFAULT_IMAGE_STYLE = "watercolor"
|
||||
DEFAULT_IMAGE_SIZE = "1280x720"
|
||||
@@ -18,9 +15,6 @@ DEFAULT_MAX_ATTEMPTS = 60
|
||||
@dataclass(frozen=True)
|
||||
class MemoirImageSettings:
|
||||
enabled: bool = False
|
||||
max_per_chapter: int = DEFAULT_MAX_IMAGES_PER_CHAPTER
|
||||
chars_per_extra_image: int = DEFAULT_CHARS_PER_EXTRA_IMAGE
|
||||
max_images_cap: int = DEFAULT_MAX_IMAGES_CAP
|
||||
provider: str = DEFAULT_IMAGE_PROVIDER
|
||||
default_style: str = DEFAULT_IMAGE_STYLE
|
||||
default_size: str = DEFAULT_IMAGE_SIZE
|
||||
@@ -33,9 +27,6 @@ class MemoirImageSettings:
|
||||
s = settings
|
||||
return cls(
|
||||
enabled=bool(s.memoir_image_enabled),
|
||||
max_per_chapter=s.memoir_image_max_per_chapter,
|
||||
chars_per_extra_image=s.memoir_image_chars_per_extra,
|
||||
max_images_cap=s.memoir_image_max_cap,
|
||||
provider=s.memoir_image_provider or DEFAULT_IMAGE_PROVIDER,
|
||||
default_style=s.memoir_image_style_default or DEFAULT_IMAGE_STYLE,
|
||||
default_size=s.memoir_image_size_default or DEFAULT_IMAGE_SIZE,
|
||||
@@ -49,15 +40,3 @@ class MemoirImageSettings:
|
||||
from app.core.config import settings as _s
|
||||
|
||||
return cls.from_settings(_s)
|
||||
|
||||
def effective_max_images(self, content_length: int) -> int:
|
||||
"""根据正文字数动态计算单章允许的最大图片数。"""
|
||||
base_max = max(self.max_per_chapter, 0)
|
||||
effective_cap = max(self.max_images_cap, base_max)
|
||||
safe_length = max(content_length, 0)
|
||||
extra = (
|
||||
safe_length // self.chars_per_extra_image
|
||||
if self.chars_per_extra_image > 0
|
||||
else 0
|
||||
)
|
||||
return min(base_max + extra, effective_cap)
|
||||
|
||||
@@ -181,34 +181,6 @@ def _memoir_image_from_asset(
|
||||
)
|
||||
|
||||
|
||||
def _select_placeholders_for_effective_max(
|
||||
placeholders: list[dict],
|
||||
existing_images: list[dict] | None,
|
||||
effective_max: int,
|
||||
) -> list[dict]:
|
||||
existing_placeholders = {
|
||||
item.get("placeholder")
|
||||
for item in normalize_image_assets(existing_images)
|
||||
if item.get("placeholder")
|
||||
}
|
||||
existing_count_in_content = sum(
|
||||
1 for item in placeholders if item.get("placeholder") in existing_placeholders
|
||||
)
|
||||
remaining_new_slots = max(0, effective_max - existing_count_in_content)
|
||||
|
||||
selected: list[dict] = []
|
||||
for item in placeholders:
|
||||
if item.get("placeholder") in existing_placeholders:
|
||||
selected.append(item)
|
||||
continue
|
||||
if remaining_new_slots <= 0:
|
||||
continue
|
||||
selected.append(item)
|
||||
remaining_new_slots -= 1
|
||||
|
||||
return [{**item, "index": index} for index, item in enumerate(selected)]
|
||||
|
||||
|
||||
def _coerce_state(model: MemoirState) -> MemoirStateSchema:
|
||||
"""将数据库模型转换为 Schema"""
|
||||
return MemoirStateSchema.model_validate(
|
||||
|
||||
Reference in New Issue
Block a user