feat: init 0
This commit is contained in:
commit
2050622dea
|
|
@ -0,0 +1,190 @@
|
|||
# ============================================
|
||||
# Python项目 .gitignore 文件
|
||||
# 生成日期:2025-12-05
|
||||
# ============================================
|
||||
|
||||
# 1. Python字节码和编译文件[1](@ref)[3](@ref)[6](@ref)
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
|
||||
# C扩展模块
|
||||
*.so
|
||||
|
||||
# 2. 分发和打包文件[1](@ref)[3](@ref)[6](@ref)
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller生成文件[1](@ref)[3](@ref)
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# 安装日志
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# 3. 单元测试和覆盖率报告[3](@ref)[6](@ref)
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# 4. 翻译文件
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# 5. 框架特定文件
|
||||
# Django[3](@ref)[6](@ref)
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
*/migrations/*.py
|
||||
!*/migrations/__init__.py
|
||||
|
||||
# Flask[1](@ref)[3](@ref)
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy
|
||||
.scrapy
|
||||
|
||||
# Sphinx文档
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# 6. Jupyter Notebook和IPython[3](@ref)[6](@ref)
|
||||
.ipynb_checkpoints
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# 7. 环境管理文件
|
||||
# pyenv版本文件[3](@ref)[6](@ref)
|
||||
# .python-version
|
||||
|
||||
# pipenv(根据项目需要决定是否忽略)[3](@ref)[6](@ref)
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry(根据项目需要决定是否忽略)[3](@ref)[6](@ref)
|
||||
#poetry.lock
|
||||
|
||||
# pdm[6](@ref)
|
||||
#pdm.lock
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582包目录[3](@ref)[6](@ref)
|
||||
__pypackages__/
|
||||
|
||||
# Celery相关文件[3](@ref)[6](@ref)
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath解析文件
|
||||
*.sage.py
|
||||
|
||||
# 8. 虚拟环境和环境变量文件[1](@ref)[3](@ref)[5](@ref)
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# 9. IDE和编辑器配置文件[4](@ref)[5](@ref)
|
||||
# PyCharm/IntelliJ IDEA
|
||||
.idea/
|
||||
|
||||
# VS Code
|
||||
.vscode/
|
||||
*.vscode/settings.json
|
||||
*.code-workspace
|
||||
|
||||
# Spyder项目设置
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope项目设置
|
||||
.ropeproject
|
||||
|
||||
# 10. 文档生成
|
||||
# mkdocs文档
|
||||
/site
|
||||
|
||||
# 11. 类型检查工具缓存[3](@ref)[6](@ref)
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre类型检查器
|
||||
.pyre/
|
||||
|
||||
# pytype静态类型分析器
|
||||
.pytype/
|
||||
|
||||
# Cython调试符号
|
||||
cython_debug/
|
||||
|
||||
# 12. 操作系统特定文件(macOS)[2](@ref)[4](@ref)
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
Icon
|
||||
._*
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
# 13. 项目特定自定义忽略(根据实际情况添加)
|
||||
# 日志文件
|
||||
*.log
|
||||
.*.log
|
||||
|
||||
# 本地配置文件
|
||||
local_config.py
|
||||
|
||||
# 数据目录(如果需要)
|
||||
# datas/
|
||||
# docker_image_build_tmp/
|
||||
# logs/
|
||||
# results/
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
fastapi
|
||||
uvicorn[standard]
|
||||
httpx[socks]
|
||||
qdrant-client[httpx]
|
||||
python-dotenv
|
||||
pytest-asyncio
|
||||
pymupdf
|
||||
python-docx
|
||||
scikit-learn
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
import asyncio, warnings, copy, time
|
||||
|
||||
|
||||
class BaseNode:
|
||||
def __init__(self):
|
||||
self.params, self.successors = {}, {}
|
||||
|
||||
def set_params(self, params):
|
||||
self.params = params
|
||||
|
||||
def next(self, node, action="default"):
|
||||
if action in self.successors:
|
||||
warnings.warn(f"Overwriting successor for action '{action}'")
|
||||
self.successors[action] = node
|
||||
return node
|
||||
|
||||
def prep(self, shared):
|
||||
pass
|
||||
|
||||
def exec(self, prep_res):
|
||||
pass
|
||||
|
||||
def post(self, shared, prep_res, exec_res):
|
||||
pass
|
||||
|
||||
def _exec(self, prep_res):
|
||||
return self.exec(prep_res)
|
||||
|
||||
def _run(self, shared):
|
||||
p = self.prep(shared)
|
||||
e = self._exec(p)
|
||||
return self.post(shared, p, e)
|
||||
|
||||
def run(self, shared):
|
||||
if self.successors:
|
||||
warnings.warn("Node won't run successors. Use Flow.")
|
||||
return self._run(shared)
|
||||
|
||||
def __rshift__(self, other):
|
||||
return self.next(other)
|
||||
|
||||
def __sub__(self, action):
|
||||
if isinstance(action, str):
|
||||
return _ConditionalTransition(self, action)
|
||||
raise TypeError("Action must be a string")
|
||||
|
||||
|
||||
class _ConditionalTransition:
|
||||
def __init__(self, src, action):
|
||||
self.src, self.action = src, action
|
||||
|
||||
def __rshift__(self, tgt):
|
||||
return self.src.next(tgt, self.action)
|
||||
|
||||
|
||||
class Node(BaseNode):
|
||||
def __init__(self, max_retries=1, wait=0):
|
||||
super().__init__()
|
||||
self.max_retries, self.wait = max_retries, wait
|
||||
|
||||
def exec_fallback(self, prep_res, exc):
|
||||
raise exc
|
||||
|
||||
def _exec(self, prep_res):
|
||||
for self.cur_retry in range(self.max_retries):
|
||||
try:
|
||||
return self.exec(prep_res)
|
||||
except Exception as e:
|
||||
if self.cur_retry == self.max_retries - 1:
|
||||
return self.exec_fallback(prep_res, e)
|
||||
if self.wait > 0:
|
||||
time.sleep(self.wait)
|
||||
|
||||
|
||||
class BatchNode(Node):
|
||||
def _exec(self, items):
|
||||
return [super(BatchNode, self)._exec(i) for i in (items or [])]
|
||||
|
||||
|
||||
class Flow(BaseNode):
|
||||
def __init__(self, start=None):
|
||||
super().__init__()
|
||||
self.start_node = start
|
||||
|
||||
def start(self, start):
|
||||
self.start_node = start
|
||||
return start
|
||||
|
||||
def get_next_node(self, curr, action):
|
||||
nxt = curr.successors.get(action or "default")
|
||||
if not nxt and curr.successors:
|
||||
warnings.warn(f"Flow ends: '{action}' not found in {list(curr.successors)}")
|
||||
return nxt
|
||||
|
||||
def _orch(self, shared, params=None):
|
||||
curr, p, last_action = copy.copy(self.start_node), (params or {**self.params}), None
|
||||
while curr:
|
||||
curr.set_params(p)
|
||||
last_action = curr._run(shared)
|
||||
curr = copy.copy(self.get_next_node(curr, last_action))
|
||||
return last_action
|
||||
|
||||
def _run(self, shared):
|
||||
p = self.prep(shared)
|
||||
o = self._orch(shared)
|
||||
return self.post(shared, p, o)
|
||||
|
||||
def post(self, shared, prep_res, exec_res):
|
||||
return exec_res
|
||||
|
||||
|
||||
class BatchFlow(Flow):
|
||||
def _run(self, shared):
|
||||
pr = self.prep(shared) or []
|
||||
for bp in pr:
|
||||
self._orch(shared, {**self.params, **bp})
|
||||
return self.post(shared, pr, None)
|
||||
|
||||
|
||||
class AsyncNode(Node):
|
||||
async def prep_async(self, shared):
|
||||
pass
|
||||
|
||||
async def exec_async(self, prep_res):
|
||||
pass
|
||||
|
||||
async def exec_fallback_async(self, prep_res, exc):
|
||||
raise exc
|
||||
|
||||
async def post_async(self, shared, prep_res, exec_res):
|
||||
pass
|
||||
|
||||
async def _exec(self, prep_res):
|
||||
for self.cur_retry in range(self.max_retries):
|
||||
try:
|
||||
return await self.exec_async(prep_res)
|
||||
except Exception as e:
|
||||
if self.cur_retry == self.max_retries - 1:
|
||||
return await self.exec_fallback_async(prep_res, e)
|
||||
if self.wait > 0:
|
||||
await asyncio.sleep(self.wait)
|
||||
|
||||
async def run_async(self, shared):
|
||||
if self.successors:
|
||||
warnings.warn("Node won't run successors. Use AsyncFlow.")
|
||||
return await self._run_async(shared)
|
||||
|
||||
async def _run_async(self, shared):
|
||||
p = await self.prep_async(shared)
|
||||
e = await self._exec(p)
|
||||
return await self.post_async(shared, p, e)
|
||||
|
||||
def _run(self, shared):
|
||||
raise RuntimeError("Use run_async.")
|
||||
|
||||
|
||||
class AsyncBatchNode(AsyncNode, BatchNode):
|
||||
async def _exec(self, items):
|
||||
return [await super(AsyncBatchNode, self)._exec(i) for i in items]
|
||||
|
||||
|
||||
class AsyncParallelBatchNode(AsyncNode, BatchNode):
|
||||
async def _exec(self, items):
|
||||
return await asyncio.gather(*(super(AsyncParallelBatchNode, self)._exec(i) for i in items))
|
||||
|
||||
|
||||
class AsyncFlow(Flow, AsyncNode):
|
||||
async def _orch_async(self, shared, params=None):
|
||||
curr, p, last_action = copy.copy(self.start_node), (params or {**self.params}), None
|
||||
while curr:
|
||||
curr.set_params(p)
|
||||
last_action = await curr._run_async(shared) if isinstance(curr, AsyncNode) else curr._run(shared)
|
||||
curr = copy.copy(self.get_next_node(curr, last_action))
|
||||
return last_action
|
||||
|
||||
async def _run_async(self, shared):
|
||||
p = await self.prep_async(shared)
|
||||
o = await self._orch_async(shared)
|
||||
return await self.post_async(shared, p, o)
|
||||
|
||||
async def post_async(self, shared, prep_res, exec_res):
|
||||
return exec_res
|
||||
|
||||
|
||||
class AsyncBatchFlow(AsyncFlow, BatchFlow):
|
||||
async def _run_async(self, shared):
|
||||
pr = await self.prep_async(shared) or []
|
||||
for bp in pr:
|
||||
await self._orch_async(shared, {**self.params, **bp})
|
||||
return await self.post_async(shared, pr, None)
|
||||
|
||||
|
||||
class AsyncParallelBatchFlow(AsyncFlow, BatchFlow):
|
||||
async def _run_async(self, shared):
|
||||
pr = await self.prep_async(shared) or []
|
||||
await asyncio.gather(*(self._orch_async(shared, {**self.params, **bp}) for bp in pr))
|
||||
return await self.post_async(shared, pr, None)
|
||||
Loading…
Reference in New Issue