sdpy-kit 0.7.2__tar.gz → 0.7.3__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.
Files changed (58) hide show
  1. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/PKG-INFO +3 -2
  2. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/README.md +2 -1
  3. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/__init__.py +1 -1
  4. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/runner.py +32 -4
  5. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/.gitignore +0 -0
  6. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/__init__.py +0 -0
  7. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/_retry_after.py +0 -0
  8. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/_service_base.py +0 -0
  9. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/chat_service.py +0 -0
  10. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/embedding_service.py +0 -0
  11. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/exceptions.py +0 -0
  12. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/failover.py +0 -0
  13. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/image_service.py +0 -0
  14. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/model_builder.py +0 -0
  15. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/model_client.py +0 -0
  16. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/pool.py +0 -0
  17. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/profiles.py +0 -0
  18. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/rerank_service.py +0 -0
  19. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/rerank_transport.py +0 -0
  20. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/sdk_client.py +0 -0
  21. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/ai/types.py +0 -0
  22. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/common_kit.py +0 -0
  23. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/config/__init__.py +0 -0
  24. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/config/kit_config.py +0 -0
  25. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/config/log_config.py +0 -0
  26. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/crawl/__init__.py +0 -0
  27. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/crawl/article_io.py +0 -0
  28. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/crawl/article_models.py +0 -0
  29. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/crawl/deepseek_kit.py +0 -0
  30. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/crawl/web_article_kit.py +0 -0
  31. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/crawl/wx_article_kit.py +0 -0
  32. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/__init__.py +0 -0
  33. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/audit.py +0 -0
  34. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/base_db_kit.py +0 -0
  35. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/crud.py +0 -0
  36. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/engine.py +0 -0
  37. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/exceptions.py +0 -0
  38. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/models/__init__.py +0 -0
  39. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/models/base.py +0 -0
  40. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/mysql_kit.py +0 -0
  41. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/pg_kit.py +0 -0
  42. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/query.py +0 -0
  43. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/session.py +0 -0
  44. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/sqlite_kit.py +0 -0
  45. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/db/transaction.py +0 -0
  46. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/decima_kit.py +0 -0
  47. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/docs/__init__.py +0 -0
  48. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/docs/anydoc_kit.py +0 -0
  49. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/docs/docx_kit.py +0 -0
  50. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/docs/marker_kit.py +0 -0
  51. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/docs/md2doc_kit.py +0 -0
  52. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/docs/mineru_kit.py +0 -0
  53. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/docs/rc_docparser_kit.py +0 -0
  54. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/file_kit.py +0 -0
  55. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/laya_kit.py +0 -0
  56. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/license_kit.py +0 -0
  57. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/kit/redis_kit.py +0 -0
  58. {sdpy_kit-0.7.2 → sdpy_kit-0.7.3}/pyproject.toml +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sdpy-kit
3
- Version: 0.7.2
3
+ Version: 0.7.3
4
4
  Summary: SDPY Kit——统一数据库访问层(PG/MySQL/SQLite)与 AI/Redis/文件/文档/向量工具集
5
5
  Author-email: Clark <changhongyuan@126.com>
6
6
  License-Expression: MIT
@@ -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:
@@ -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:
@@ -23,7 +23,7 @@ Author: Clark Chang
23
23
  数据库访问通过 kit.db 子包提供(基于 SQLModel)。
24
24
  """
25
25
 
26
- __version__ = "0.7.2"
26
+ __version__ = "0.7.3"
27
27
 
28
28
  from kit.db import (
29
29
  MYSQL,
@@ -846,10 +846,14 @@ class _StreamIterator:
846
846
  直接 ``for`` 中途 ``break`` 或迭代器被 GC,``close``/``__del__`` 也会
847
847
  兜底取消后台 producer,避免任务残留。
848
848
 
849
- 流结束后可读 ``reasoning_chars`` / ``content_chars`` / ``finish_reason`` /
850
- ``truncated`` / ``thinking_applied`` / ``json_mode_applied`` 六个只读属性
851
- (跨线程共享同一累加器:结束后为最终值,流式过程中为尽力而为的中间值;
852
- 提前 ``break`` 时为截至中断的累计值)。
849
+ 流结束后可读八个只读属性:``reasoning_chars`` / ``content_chars`` /
850
+ ``finish_reason`` / ``requested_max_tokens`` / ``truncated`` / ``empty_kind`` /
851
+ ``thinking_applied`` / ``json_mode_applied``(跨线程共享同一累加器:
852
+ 结束后为最终值,流式过程中为尽力而为的中间值;提前 ``break`` 时为截至
853
+ 中断的累计值)。
854
+
855
+ ``empty_kind`` 例外:**仅在流正常结束后可读**,迭代中与异常 / 中断后
856
+ 恒为 ``None``(避免把「正文还没到」误判成 ``no_finish``)。
853
857
  """
854
858
 
855
859
  def __init__(
@@ -871,6 +875,8 @@ class _StreamIterator:
871
875
  self._started = False
872
876
  self._closed = False
873
877
  self._got_first = False
878
+ # 正常收尾(收到哨兵)才置真:empty_kind 只在结束后给结论
879
+ self._exhausted = False
874
880
  self._task: concurrent.futures.Future[None] | None = None
875
881
 
876
882
  def __iter__(self) -> Iterator[str]:
@@ -931,6 +937,7 @@ class _StreamIterator:
931
937
  f"流式帧间隔超过 {_STREAM_FRAME_INTERVAL_TIMEOUT:g}s 未收到新帧"
932
938
  ) from exc
933
939
  if item is _SENTINEL:
940
+ self._exhausted = True
934
941
  self.close()
935
942
  raise StopIteration
936
943
  if isinstance(item, BaseException):
@@ -971,6 +978,27 @@ class _StreamIterator:
971
978
  """结构化输出是否生效:None 未要求注入 / True 已注入 / False 被忽略。"""
972
979
  return self._stats.json_mode_applied
973
980
 
981
+ @property
982
+ def requested_max_tokens(self) -> int | None:
983
+ """本次实际下发的输出上限(调用方 → 档案回落);未发请求为 None。"""
984
+ return self._stats.requested_max_tokens
985
+
986
+ @property
987
+ def empty_kind(self) -> str | None:
988
+ """正文为空时的诊断分级;**仅在流正常结束后可读,其余时刻为 None**。
989
+
990
+ 取值同 ``StreamStats.empty_kind``(``budget_exhausted`` /
991
+ ``truncated_empty`` / ``reasoning_only`` / ``no_finish`` /
992
+ ``stopped_empty``;正文非空为 None)。
993
+
994
+ 迭代中不给中间结论:此时正文尚未产出,``content_chars`` 恒为 0,
995
+ 直接转发会把「还没出正文」误报成 ``no_finish``;异常 / 中途 ``break``
996
+ 同理不置收尾标志。
997
+ """
998
+ if not self._exhausted:
999
+ return None
1000
+ return self._stats.empty_kind
1001
+
974
1002
 
975
1003
  async def _delayed_close(services: list[Service]) -> None:
976
1004
  """延迟回收旧 service:给在途调用留宽限期,到期统一关闭(须在 loop 内)。"""
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