sdpy-kit 0.7.2__tar.gz → 0.7.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/PKG-INFO +11 -9
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/README.md +10 -8
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/__init__.py +1 -1
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/runner.py +36 -7
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/pyproject.toml +2 -2
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/.gitignore +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/__init__.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/_retry_after.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/_service_base.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/chat_service.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/embedding_service.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/exceptions.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/failover.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/image_service.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/model_builder.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/model_client.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/pool.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/profiles.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/rerank_service.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/rerank_transport.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/sdk_client.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/ai/types.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/common_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/config/__init__.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/config/kit_config.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/config/log_config.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/crawl/__init__.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/crawl/article_io.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/crawl/article_models.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/crawl/deepseek_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/crawl/web_article_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/crawl/wx_article_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/__init__.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/audit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/base_db_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/crud.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/engine.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/exceptions.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/models/__init__.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/models/base.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/mysql_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/pg_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/query.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/session.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/sqlite_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/db/transaction.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/decima_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/docs/__init__.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/docs/anydoc_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/docs/docx_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/docs/marker_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/docs/md2doc_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/docs/mineru_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/docs/rc_docparser_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/file_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/laya_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/license_kit.py +0 -0
- {sdpy_kit-0.7.2 → sdpy_kit-0.7.4}/kit/redis_kit.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: sdpy-kit
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.4
|
|
4
4
|
Summary: SDPY Kit——统一数据库访问层(PG/MySQL/SQLite)与 AI/Redis/文件/文档/向量工具集
|
|
5
5
|
Author-email: Clark <changhongyuan@126.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -180,7 +180,7 @@ SQLITE_DB_PATH=./data/sqlite.db
|
|
|
180
180
|
# MinerU(仅精准解析需要 Key,Agent 轻量解析免登录)
|
|
181
181
|
# MINERU_API_KEY=
|
|
182
182
|
|
|
183
|
-
# Marker
|
|
183
|
+
# Marker(0.7.0 起暂停发布,无 marker extra;需要请用 sdpy-kit==0.6.10)
|
|
184
184
|
# MARKER_MODE=fast # None=按设备自动(GPU→balanced / CPU、MPS→fast)
|
|
185
185
|
# MARKER_HF_ENDPOINT=https://hf-mirror.com
|
|
186
186
|
# MARKER_HF_DISABLE_XET=true
|
|
@@ -812,7 +812,7 @@ page = qb.paginate(page=1, per_page=20) # {"items", "total", ...}
|
|
|
812
812
|
传输:chat / embedding / image 走 `openai` SDK(`>=3.44,<4`,
|
|
813
813
|
自带 `httpx2`),rerank 走 httpx 自研传输(SDK 无 `/rerank` 资源)。
|
|
814
814
|
档案里的 `endpoint` **对前三类不再生效**——SDK 固定拼 `/chat/completions`、
|
|
815
|
-
`/embeddings`、`/images/generations`,仅 rerank
|
|
815
|
+
`/embeddings`、`/images/generations`,仅 rerank 仍使用该字段(探活走 openai SDK 的 `GET {base_url}/models`,不读本字段)。
|
|
816
816
|
|
|
817
817
|
> 安装提示:`openai` 3.x 会引入 `httpx2`,与 rerank 用的 `httpx` 并存(两个包名不同,不冲突)。
|
|
818
818
|
|
|
@@ -838,10 +838,10 @@ shutdown() # 应用退出前
|
|
|
838
838
|
| chat | `chat_stream(messages, *, max_tokens=None, thinking=None, json_mode=None, response_format=None) -> Iterator[str]` | 同步流式逐 token 迭代器(建议 `with` 使用);结束后可读 `reasoning_chars` / `content_chars` / `finish_reason` / `requested_max_tokens` / `truncated` / `empty_kind` / `thinking_applied` / `json_mode_applied` |
|
|
839
839
|
| embedding | `embed_text(text) -> list[float]` | 单文本向量化 |
|
|
840
840
|
| embedding | `embed_texts(texts) -> list[list[float]]` | 批量向量化 |
|
|
841
|
-
| rerank | `rerank(query, documents, top_n=None) -> list[RerankHit]` | 返回 `RerankHit`(`index` / `score` / `document`)降序列表;**`top_n` 是返回条数上限,由 kit 本地裁剪**(服务端返回超量也按分数截断),`top_n=None`
|
|
841
|
+
| rerank | `rerank(query, documents, top_n=None) -> list[RerankHit]` | 返回 `RerankHit`(`index` / `score` / `document`)降序列表;**`top_n` 是返回条数上限,由 kit 本地裁剪**(服务端返回超量也按分数截断),`top_n=None` 返回全部命中,`top_n<=0` 直接返回空列表 |
|
|
842
842
|
| image | `generate_image(prompt, *, size=None, n=1, return_base64=False, ratio=None) -> ImageResult` | 文生图,返回 `ImageResult`(`url` / `b64` 至少一个非空) |
|
|
843
843
|
| 管理 | `use(model_type, profile) -> None` | 切换该类型当前档案(`chat` / `embedding` / `rerank` / `image`) |
|
|
844
|
-
| 管理 | `available(model_type) -> list[ProfileStatus]` | 各档案状态快照(含未配置密钥与被剔除者);**类型未在 `ai_models.json` 中配置时返回 `[]
|
|
844
|
+
| 管理 | `available(model_type) -> list[ProfileStatus]` | 各档案状态快照(含未配置密钥与被剔除者);**类型未在 `ai_models.json` 中配置时返回 `[]`**(不再抛异常),类型名非法抛 `AIModelTypeNotConfiguredError`(`AIConfigError` 子类) |
|
|
845
845
|
| 管理 | `reload_config(*, model_type=None, reload_file=False, probe=True, immediate=False) -> ReloadResult` | 配置热重载,改密钥 / 档案后无需重启;同时清空思考/结构化输出的告警去重表(修正档案后同一原因会重新提示) |
|
|
846
846
|
|
|
847
847
|
**可用性查询(`available`)**:`available` 返回的是**状态快照**,不是「可用档案列表」。
|
|
@@ -885,7 +885,8 @@ with AI.chat_stream([{"role": "user", "content": "写一首短诗"}]) as stream:
|
|
|
885
885
|
| `no_finish` | 结束原因缺失或非 `stop`(端点未发送 `finish_reason`) | 可原样重试;连续出现检查端点 |
|
|
886
886
|
| `stopped_empty` | 无推理、`finish_reason=stop`、正文 0 | 检查提示词与模型输出 |
|
|
887
887
|
|
|
888
|
-
正文非空时 `empty_kind is None`。判定只用「是否截断 + 是否有推理 + 结束原因」,不依赖 token 数(kit 目前不采集 `usage
|
|
888
|
+
正文非空时 `empty_kind is None`。判定只用「是否截断 + 是否有推理 + 结束原因」,不依赖 token 数(kit 目前不采集 `usage`)。
|
|
889
|
+
注意:该属性**仅在流正常结束后可读**,迭代中与异常 / 中断后为 `None`(避免把「正文还没到」误判成 `no_finish`);`requested_max_tokens` 无此限制。
|
|
889
890
|
|
|
890
891
|
```python
|
|
891
892
|
with AI.chat_stream(messages, max_tokens=450) as stream:
|
|
@@ -1010,7 +1011,7 @@ await service.close()
|
|
|
1010
1011
|
| `RerankService` | `rerank(query, documents, *, top_n=None) -> list[RerankHit]`(已按 score 降序) |
|
|
1011
1012
|
| `ImageService` | `generate(prompt, *, size=None, n=1, return_base64=False, ratio=None) -> ImageResult` |
|
|
1012
1013
|
| `ModelBuilder` | `build(model_type, model=None, *, api_key=None)` 及各类型专用 `build_chat / build_embedding / build_rerank / build_image` |
|
|
1013
|
-
| `
|
|
1014
|
+
| `SdkServiceBase` | `profile` 属性、`await close()`、支持 `async with` |
|
|
1014
1015
|
|
|
1015
1016
|
**embedding 维度契约**:`ai_models.json` 里 embedding 档案的 `dimension` 是**目标向量维度**
|
|
1016
1017
|
(不是模型原生维度),`EmbeddingService` 保证输出恒等于它:
|
|
@@ -1039,7 +1040,8 @@ from kit.ai.exceptions import (
|
|
|
1039
1040
|
| 异常 | 触发场景 / 可用属性 |
|
|
1040
1041
|
|------|---------------------|
|
|
1041
1042
|
| `AIError` | 基类 |
|
|
1042
|
-
| `AIConfigError` |
|
|
1043
|
+
| `AIConfigError` | 档案缺失或非法、档案不存在、密钥未配置、必填字段缺失、`default_profile` 未在 `profiles` 中定义(加载期校验) |
|
|
1044
|
+
| `AIModelTypeNotConfiguredError` | 模型类型名非法(合法类型但未配置返回 `[]` 不抛);`AIConfigError` 子类 |
|
|
1043
1045
|
| `AIRequestError` | 单次请求失败;`status_code`、`retry_after`(429 时解析 `Retry-After`) |
|
|
1044
1046
|
| `AITimeoutError` | 请求超时(继承 `AIRequestError`) |
|
|
1045
1047
|
| `AIAggregateError` | 全部候选失败或整链预算耗尽;`tried`、`statuses`、`last_error`、`budget_exhausted` |
|
|
@@ -1644,7 +1646,7 @@ AI 功能需要在项目根目录提供 `config/ai_models.json`(chat / embeddi
|
|
|
1644
1646
|
| 层级 | 字段 | 说明 |
|
|
1645
1647
|
|------|------|------|
|
|
1646
1648
|
| 档案级 | `endpoint` | 请求路径。**仅 rerank 生效**:chat / embedding / image 由 openai SDK 固定拼路径,本字段被忽略(保留仅为兼容旧配置,不报错) |
|
|
1647
|
-
| 档案级 | `timeout` | 请求超时秒数(默认 60);SDK
|
|
1649
|
+
| 档案级 | `timeout` | 请求超时秒数(默认 60);SDK 侧为单次调用总超时。**流式例外**:流式请求 `timeout=None`,由门面首帧 60s + 帧间隔 120s 兜底 |
|
|
1648
1650
|
| 档案级 | `max_tokens` | 输出上限(chat 用);`AI.chat_ask/chat_complete/chat_stream` 也可按调用点传参,逐级回落:调用点 → 档案 → provider 默认 |
|
|
1649
1651
|
| 档案级 | `retries` | 5xx 重试次数(默认 2;超时不重试,候选链切换才是有效重试) |
|
|
1650
1652
|
| 档案级 | `extra_body` | 厂商专有请求体字段透传(如 GLM/Qwen 关闭思考的 `{"thinking": {"type": "disabled"}}`、`{"reasoning_effort": "low"}`);与服务构造的同名键冲突时**以服务的值为准**,故 `model` / `messages` / `stream` 等保留键不可覆盖;改名类需求(如 OpenAI o 系列的 `max_completion_tokens`)无法用它实现。逐调用 `thinking` 与之同键时**以逐调用为准**并打 `WARNING`。改文件后需 `reload_config(reload_file=True)` 生效 |
|
|
@@ -98,7 +98,7 @@ SQLITE_DB_PATH=./data/sqlite.db
|
|
|
98
98
|
# MinerU(仅精准解析需要 Key,Agent 轻量解析免登录)
|
|
99
99
|
# MINERU_API_KEY=
|
|
100
100
|
|
|
101
|
-
# Marker
|
|
101
|
+
# Marker(0.7.0 起暂停发布,无 marker extra;需要请用 sdpy-kit==0.6.10)
|
|
102
102
|
# MARKER_MODE=fast # None=按设备自动(GPU→balanced / CPU、MPS→fast)
|
|
103
103
|
# MARKER_HF_ENDPOINT=https://hf-mirror.com
|
|
104
104
|
# MARKER_HF_DISABLE_XET=true
|
|
@@ -730,7 +730,7 @@ page = qb.paginate(page=1, per_page=20) # {"items", "total", ...}
|
|
|
730
730
|
传输:chat / embedding / image 走 `openai` SDK(`>=3.44,<4`,
|
|
731
731
|
自带 `httpx2`),rerank 走 httpx 自研传输(SDK 无 `/rerank` 资源)。
|
|
732
732
|
档案里的 `endpoint` **对前三类不再生效**——SDK 固定拼 `/chat/completions`、
|
|
733
|
-
`/embeddings`、`/images/generations`,仅 rerank
|
|
733
|
+
`/embeddings`、`/images/generations`,仅 rerank 仍使用该字段(探活走 openai SDK 的 `GET {base_url}/models`,不读本字段)。
|
|
734
734
|
|
|
735
735
|
> 安装提示:`openai` 3.x 会引入 `httpx2`,与 rerank 用的 `httpx` 并存(两个包名不同,不冲突)。
|
|
736
736
|
|
|
@@ -756,10 +756,10 @@ shutdown() # 应用退出前
|
|
|
756
756
|
| chat | `chat_stream(messages, *, max_tokens=None, thinking=None, json_mode=None, response_format=None) -> Iterator[str]` | 同步流式逐 token 迭代器(建议 `with` 使用);结束后可读 `reasoning_chars` / `content_chars` / `finish_reason` / `requested_max_tokens` / `truncated` / `empty_kind` / `thinking_applied` / `json_mode_applied` |
|
|
757
757
|
| embedding | `embed_text(text) -> list[float]` | 单文本向量化 |
|
|
758
758
|
| embedding | `embed_texts(texts) -> list[list[float]]` | 批量向量化 |
|
|
759
|
-
| rerank | `rerank(query, documents, top_n=None) -> list[RerankHit]` | 返回 `RerankHit`(`index` / `score` / `document`)降序列表;**`top_n` 是返回条数上限,由 kit 本地裁剪**(服务端返回超量也按分数截断),`top_n=None`
|
|
759
|
+
| rerank | `rerank(query, documents, top_n=None) -> list[RerankHit]` | 返回 `RerankHit`(`index` / `score` / `document`)降序列表;**`top_n` 是返回条数上限,由 kit 本地裁剪**(服务端返回超量也按分数截断),`top_n=None` 返回全部命中,`top_n<=0` 直接返回空列表 |
|
|
760
760
|
| image | `generate_image(prompt, *, size=None, n=1, return_base64=False, ratio=None) -> ImageResult` | 文生图,返回 `ImageResult`(`url` / `b64` 至少一个非空) |
|
|
761
761
|
| 管理 | `use(model_type, profile) -> None` | 切换该类型当前档案(`chat` / `embedding` / `rerank` / `image`) |
|
|
762
|
-
| 管理 | `available(model_type) -> list[ProfileStatus]` | 各档案状态快照(含未配置密钥与被剔除者);**类型未在 `ai_models.json` 中配置时返回 `[]
|
|
762
|
+
| 管理 | `available(model_type) -> list[ProfileStatus]` | 各档案状态快照(含未配置密钥与被剔除者);**类型未在 `ai_models.json` 中配置时返回 `[]`**(不再抛异常),类型名非法抛 `AIModelTypeNotConfiguredError`(`AIConfigError` 子类) |
|
|
763
763
|
| 管理 | `reload_config(*, model_type=None, reload_file=False, probe=True, immediate=False) -> ReloadResult` | 配置热重载,改密钥 / 档案后无需重启;同时清空思考/结构化输出的告警去重表(修正档案后同一原因会重新提示) |
|
|
764
764
|
|
|
765
765
|
**可用性查询(`available`)**:`available` 返回的是**状态快照**,不是「可用档案列表」。
|
|
@@ -803,7 +803,8 @@ with AI.chat_stream([{"role": "user", "content": "写一首短诗"}]) as stream:
|
|
|
803
803
|
| `no_finish` | 结束原因缺失或非 `stop`(端点未发送 `finish_reason`) | 可原样重试;连续出现检查端点 |
|
|
804
804
|
| `stopped_empty` | 无推理、`finish_reason=stop`、正文 0 | 检查提示词与模型输出 |
|
|
805
805
|
|
|
806
|
-
正文非空时 `empty_kind is None`。判定只用「是否截断 + 是否有推理 + 结束原因」,不依赖 token 数(kit 目前不采集 `usage
|
|
806
|
+
正文非空时 `empty_kind is None`。判定只用「是否截断 + 是否有推理 + 结束原因」,不依赖 token 数(kit 目前不采集 `usage`)。
|
|
807
|
+
注意:该属性**仅在流正常结束后可读**,迭代中与异常 / 中断后为 `None`(避免把「正文还没到」误判成 `no_finish`);`requested_max_tokens` 无此限制。
|
|
807
808
|
|
|
808
809
|
```python
|
|
809
810
|
with AI.chat_stream(messages, max_tokens=450) as stream:
|
|
@@ -928,7 +929,7 @@ await service.close()
|
|
|
928
929
|
| `RerankService` | `rerank(query, documents, *, top_n=None) -> list[RerankHit]`(已按 score 降序) |
|
|
929
930
|
| `ImageService` | `generate(prompt, *, size=None, n=1, return_base64=False, ratio=None) -> ImageResult` |
|
|
930
931
|
| `ModelBuilder` | `build(model_type, model=None, *, api_key=None)` 及各类型专用 `build_chat / build_embedding / build_rerank / build_image` |
|
|
931
|
-
| `
|
|
932
|
+
| `SdkServiceBase` | `profile` 属性、`await close()`、支持 `async with` |
|
|
932
933
|
|
|
933
934
|
**embedding 维度契约**:`ai_models.json` 里 embedding 档案的 `dimension` 是**目标向量维度**
|
|
934
935
|
(不是模型原生维度),`EmbeddingService` 保证输出恒等于它:
|
|
@@ -957,7 +958,8 @@ from kit.ai.exceptions import (
|
|
|
957
958
|
| 异常 | 触发场景 / 可用属性 |
|
|
958
959
|
|------|---------------------|
|
|
959
960
|
| `AIError` | 基类 |
|
|
960
|
-
| `AIConfigError` |
|
|
961
|
+
| `AIConfigError` | 档案缺失或非法、档案不存在、密钥未配置、必填字段缺失、`default_profile` 未在 `profiles` 中定义(加载期校验) |
|
|
962
|
+
| `AIModelTypeNotConfiguredError` | 模型类型名非法(合法类型但未配置返回 `[]` 不抛);`AIConfigError` 子类 |
|
|
961
963
|
| `AIRequestError` | 单次请求失败;`status_code`、`retry_after`(429 时解析 `Retry-After`) |
|
|
962
964
|
| `AITimeoutError` | 请求超时(继承 `AIRequestError`) |
|
|
963
965
|
| `AIAggregateError` | 全部候选失败或整链预算耗尽;`tried`、`statuses`、`last_error`、`budget_exhausted` |
|
|
@@ -1562,7 +1564,7 @@ AI 功能需要在项目根目录提供 `config/ai_models.json`(chat / embeddi
|
|
|
1562
1564
|
| 层级 | 字段 | 说明 |
|
|
1563
1565
|
|------|------|------|
|
|
1564
1566
|
| 档案级 | `endpoint` | 请求路径。**仅 rerank 生效**:chat / embedding / image 由 openai SDK 固定拼路径,本字段被忽略(保留仅为兼容旧配置,不报错) |
|
|
1565
|
-
| 档案级 | `timeout` | 请求超时秒数(默认 60);SDK
|
|
1567
|
+
| 档案级 | `timeout` | 请求超时秒数(默认 60);SDK 侧为单次调用总超时。**流式例外**:流式请求 `timeout=None`,由门面首帧 60s + 帧间隔 120s 兜底 |
|
|
1566
1568
|
| 档案级 | `max_tokens` | 输出上限(chat 用);`AI.chat_ask/chat_complete/chat_stream` 也可按调用点传参,逐级回落:调用点 → 档案 → provider 默认 |
|
|
1567
1569
|
| 档案级 | `retries` | 5xx 重试次数(默认 2;超时不重试,候选链切换才是有效重试) |
|
|
1568
1570
|
| 档案级 | `extra_body` | 厂商专有请求体字段透传(如 GLM/Qwen 关闭思考的 `{"thinking": {"type": "disabled"}}`、`{"reasoning_effort": "low"}`);与服务构造的同名键冲突时**以服务的值为准**,故 `model` / `messages` / `stream` 等保留键不可覆盖;改名类需求(如 OpenAI o 系列的 `max_completion_tokens`)无法用它实现。逐调用 `thinking` 与之同键时**以逐调用为准**并打 `WARNING`。改文件后需 `reload_config(reload_file=True)` 生效 |
|
|
@@ -816,9 +816,10 @@ class AI:
|
|
|
816
816
|
if done:
|
|
817
817
|
break
|
|
818
818
|
|
|
819
|
-
|
|
820
|
-
``
|
|
821
|
-
|
|
819
|
+
流结束后可读八个只读属性:``reasoning_chars`` / ``content_chars`` /
|
|
820
|
+
``finish_reason`` / ``requested_max_tokens`` / ``truncated`` / ``empty_kind`` /
|
|
821
|
+
``thinking_applied`` / ``json_mode_applied``,用于区分「模型没返回内容」与
|
|
822
|
+
「输出预算被思考吃光」(``empty_kind`` 给出五类归因),以及确认开关是否真的生效::
|
|
822
823
|
|
|
823
824
|
with AI.chat_stream(messages, max_tokens=450) as stream:
|
|
824
825
|
body = "".join(stream)
|
|
@@ -846,10 +847,14 @@ class _StreamIterator:
|
|
|
846
847
|
直接 ``for`` 中途 ``break`` 或迭代器被 GC,``close``/``__del__`` 也会
|
|
847
848
|
兜底取消后台 producer,避免任务残留。
|
|
848
849
|
|
|
849
|
-
|
|
850
|
-
``
|
|
851
|
-
|
|
852
|
-
|
|
850
|
+
流结束后可读八个只读属性:``reasoning_chars`` / ``content_chars`` /
|
|
851
|
+
``finish_reason`` / ``requested_max_tokens`` / ``truncated`` / ``empty_kind`` /
|
|
852
|
+
``thinking_applied`` / ``json_mode_applied``(跨线程共享同一累加器:
|
|
853
|
+
结束后为最终值,流式过程中为尽力而为的中间值;提前 ``break`` 时为截至
|
|
854
|
+
中断的累计值)。
|
|
855
|
+
|
|
856
|
+
``empty_kind`` 例外:**仅在流正常结束后可读**,迭代中与异常 / 中断后
|
|
857
|
+
恒为 ``None``(避免把「正文还没到」误判成 ``no_finish``)。
|
|
853
858
|
"""
|
|
854
859
|
|
|
855
860
|
def __init__(
|
|
@@ -871,6 +876,8 @@ class _StreamIterator:
|
|
|
871
876
|
self._started = False
|
|
872
877
|
self._closed = False
|
|
873
878
|
self._got_first = False
|
|
879
|
+
# 正常收尾(收到哨兵)才置真:empty_kind 只在结束后给结论
|
|
880
|
+
self._exhausted = False
|
|
874
881
|
self._task: concurrent.futures.Future[None] | None = None
|
|
875
882
|
|
|
876
883
|
def __iter__(self) -> Iterator[str]:
|
|
@@ -931,6 +938,7 @@ class _StreamIterator:
|
|
|
931
938
|
f"流式帧间隔超过 {_STREAM_FRAME_INTERVAL_TIMEOUT:g}s 未收到新帧"
|
|
932
939
|
) from exc
|
|
933
940
|
if item is _SENTINEL:
|
|
941
|
+
self._exhausted = True
|
|
934
942
|
self.close()
|
|
935
943
|
raise StopIteration
|
|
936
944
|
if isinstance(item, BaseException):
|
|
@@ -971,6 +979,27 @@ class _StreamIterator:
|
|
|
971
979
|
"""结构化输出是否生效:None 未要求注入 / True 已注入 / False 被忽略。"""
|
|
972
980
|
return self._stats.json_mode_applied
|
|
973
981
|
|
|
982
|
+
@property
|
|
983
|
+
def requested_max_tokens(self) -> int | None:
|
|
984
|
+
"""本次实际下发的输出上限(调用方 → 档案回落);未发请求为 None。"""
|
|
985
|
+
return self._stats.requested_max_tokens
|
|
986
|
+
|
|
987
|
+
@property
|
|
988
|
+
def empty_kind(self) -> str | None:
|
|
989
|
+
"""正文为空时的诊断分级;**仅在流正常结束后可读,其余时刻为 None**。
|
|
990
|
+
|
|
991
|
+
取值同 ``StreamStats.empty_kind``(``budget_exhausted`` /
|
|
992
|
+
``truncated_empty`` / ``reasoning_only`` / ``no_finish`` /
|
|
993
|
+
``stopped_empty``;正文非空为 None)。
|
|
994
|
+
|
|
995
|
+
迭代中不给中间结论:此时正文尚未产出,``content_chars`` 恒为 0,
|
|
996
|
+
直接转发会把「还没出正文」误报成 ``no_finish``;异常 / 中途 ``break``
|
|
997
|
+
同理不置收尾标志。
|
|
998
|
+
"""
|
|
999
|
+
if not self._exhausted:
|
|
1000
|
+
return None
|
|
1001
|
+
return self._stats.empty_kind
|
|
1002
|
+
|
|
974
1003
|
|
|
975
1004
|
async def _delayed_close(services: list[Service]) -> None:
|
|
976
1005
|
"""延迟回收旧 service:给在途调用留宽限期,到期统一关闭(须在 loop 内)。"""
|
|
@@ -52,8 +52,8 @@ dynamic = ["version"]
|
|
|
52
52
|
# docx → kit.docs.docx_kit(docxtpl + python-docx,模板动态填充)
|
|
53
53
|
# docx-parse → kit.docs.rc_docparser_kit(rc-docparser,离线 docx → md + images)
|
|
54
54
|
# mineru → kit.docs.mineru_kit(requests)
|
|
55
|
-
# marker
|
|
56
|
-
#
|
|
55
|
+
# (marker 自 0.7.0 起暂停:marker-pdf 移出依赖、extra 与 wheel 内容均不包含,
|
|
56
|
+
# 需要请用 sdpy-kit[marker]==0.6.10)
|
|
57
57
|
# laya → laya_kit(laya + torch,本地类型化决策引擎 choice/score/noul)
|
|
58
58
|
# decima → decima_kit(decima-ai + onnxruntime,选项乱序不变、置信度已标定的决策模型)
|
|
59
59
|
# web-article → crawl/web_article_kit(trafilatura,通用网页文章抓取转存)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|