chore: 工作台产品化进行中的改动
把工作区里其余在制品一并入库,主要是工作台产品化的推进:
后端:新增 capability_definition / project / my_app_center / office_skill
接口与 action_definition / skill_definition / project / user_app_center
模型,config 加路由健康上报。
前端:新增 frontend/src/skills(Office 技能与 workbuddy 复刻)、
项目管理、应用中心、能力目录页,以及配套 api / store / config;
聊天侧新增 SpecialistChip / SpecialistPanel / SkillStrip / AppChatRail
等组件。
清理:移除旧 views/tools 下的单页工具(已并入工作台)、_frozen 冻结组件、
cmd/inspect_oa_debug 调试入口,以及两份调试笔记。
其它:文档与启动脚本同步。
(这批改动与上一提交的 SY23 工作并行进行,此前已在同一工作区内交织。)
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
os.environ.setdefault("ORT_DISABLE_GPU", "1")
|
||||
|
||||
try:
|
||||
from paddleocr import PaddleOCR
|
||||
except Exception:
|
||||
PaddleOCR = None
|
||||
|
||||
try:
|
||||
from rapidocr_onnxruntime import RapidOCR
|
||||
except Exception:
|
||||
RapidOCR = None
|
||||
|
||||
|
||||
def flatten_result(raw_result):
|
||||
lines = []
|
||||
text_parts = []
|
||||
for page in raw_result or []:
|
||||
if not page:
|
||||
continue
|
||||
for item in page:
|
||||
if not item or len(item) < 2:
|
||||
continue
|
||||
points = item[0]
|
||||
text_info = item[1] or []
|
||||
text = str(text_info[0] or "").strip() if len(text_info) > 0 else ""
|
||||
score = float(text_info[1] or 0) if len(text_info) > 1 else 0
|
||||
if not text:
|
||||
continue
|
||||
lines.append({
|
||||
"text": text,
|
||||
"score": score,
|
||||
"points": points,
|
||||
})
|
||||
text_parts.append(text)
|
||||
return {
|
||||
"text": "\n".join(text_parts).strip(),
|
||||
"lines": lines,
|
||||
}
|
||||
|
||||
|
||||
def run_paddle_ocr(image_path):
|
||||
if PaddleOCR is None:
|
||||
return None
|
||||
ocr = PaddleOCR(
|
||||
use_angle_cls=True,
|
||||
lang="ch",
|
||||
show_log=False,
|
||||
use_gpu=False,
|
||||
enable_mkldnn=False,
|
||||
cpu_threads=1,
|
||||
)
|
||||
result = ocr.ocr(image_path, cls=True)
|
||||
payload = flatten_result(result)
|
||||
payload["engine"] = "paddleocr"
|
||||
return payload
|
||||
|
||||
|
||||
def run_rapid_ocr(image_path):
|
||||
if RapidOCR is None:
|
||||
return None
|
||||
engine = RapidOCR()
|
||||
result, _ = engine(image_path)
|
||||
payload = {"text": "", "lines": []}
|
||||
for item in result or []:
|
||||
if not item or len(item) < 3:
|
||||
continue
|
||||
points, text, score = item[0], str(item[1] or "").strip(), float(item[2] or 0)
|
||||
if not text:
|
||||
continue
|
||||
payload["lines"].append({
|
||||
"text": text,
|
||||
"score": score,
|
||||
"points": points,
|
||||
})
|
||||
payload["text"] += f"{text}\n"
|
||||
payload["text"] = payload["text"].strip()
|
||||
payload["engine"] = "rapidocr"
|
||||
return payload
|
||||
|
||||
|
||||
def try_paddle_ocr_subprocess(image_path):
|
||||
cmd = [sys.executable, __file__, "--engine", "paddle-only", image_path]
|
||||
try:
|
||||
result = subprocess.run(
|
||||
cmd,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
env=os.environ.copy(),
|
||||
)
|
||||
except Exception:
|
||||
return None
|
||||
if result.returncode != 0:
|
||||
return None
|
||||
try:
|
||||
payload = json.loads((result.stdout or "").strip())
|
||||
except Exception:
|
||||
return None
|
||||
if not isinstance(payload, dict) or payload.get("error"):
|
||||
return None
|
||||
payload["engine"] = "paddleocr"
|
||||
return payload
|
||||
|
||||
|
||||
def main():
|
||||
args = sys.argv[1:]
|
||||
engine_mode = "auto"
|
||||
if len(args) >= 2 and args[0] == "--engine":
|
||||
engine_mode = args[1].strip().lower() or "auto"
|
||||
args = args[2:]
|
||||
|
||||
if len(args) < 1:
|
||||
print(json.dumps({"error": "missing_image_path"}, ensure_ascii=False))
|
||||
sys.exit(1)
|
||||
|
||||
image_path = args[0]
|
||||
if engine_mode == "paddle-only":
|
||||
payload = run_paddle_ocr(image_path)
|
||||
elif engine_mode == "rapid-only":
|
||||
payload = run_rapid_ocr(image_path)
|
||||
else:
|
||||
payload = try_paddle_ocr_subprocess(image_path) or run_rapid_ocr(image_path)
|
||||
if payload is None:
|
||||
print(json.dumps({"error": "ocr_engine_not_installed"}, ensure_ascii=False))
|
||||
sys.exit(1)
|
||||
print(json.dumps(payload, ensure_ascii=False))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user