初始提交:识流 AI 助手项目
微信自动回复机器人,基于截图+OCR识别消息,支持关键词规则和 AI(OpenAI/DeepSeek/Dify)自动回复。 技术栈:PySide6 + Flask + Vue3 + RapidOCR + SQLite 注:OCR大模型文件(.onnx / .pdiparams)不纳入版本控制,需单独下载。 🤖 Generated with [Qoder][https://qoder.com]
This commit is contained in:
187
app/configs/runtime_config.py
Normal file
187
app/configs/runtime_config.py
Normal file
@@ -0,0 +1,187 @@
|
||||
import os
|
||||
from typing import Any
|
||||
|
||||
DEFAULT_CONFIG: dict[str, Any] = {
|
||||
# 应用展示名称,同时作为 AppData 默认目录名的一部分
|
||||
"APP_NAME": "AiShiliu",
|
||||
# Flask 后端监听地址
|
||||
"APP_HOST": "127.0.0.1",
|
||||
# Flask 后端监听端口
|
||||
"APP_PORT": 5000,
|
||||
# 应用默认时区
|
||||
"APP_TIMEZONE": "Asia/Shanghai",
|
||||
# 已构建前端静态资源目录,留空时自动回退到项目默认目录
|
||||
"FRONTEND_STATIC_DIR": "",
|
||||
|
||||
# 日志总开关
|
||||
"LOG_ENABLED": True,
|
||||
# 日志级别
|
||||
"LOG_LEVEL": "INFO",
|
||||
# 是否写文本日志
|
||||
"LOG_TEXT_ENABLED": True,
|
||||
# 是否写JSON日志
|
||||
"LOG_JSON_ENABLED": True,
|
||||
# 单文件滚动大小(MB)
|
||||
"LOG_ROTATE_MB": 5,
|
||||
# 滚动保留份数
|
||||
"LOG_BACKUP_COUNT": 7,
|
||||
|
||||
# MySQL 主机地址(预留给后续鉴权等在线能力)
|
||||
"DB_HOST": "127.0.0.1",
|
||||
# MySQL 端口(预留)
|
||||
"DB_PORT": 3306,
|
||||
# MySQL 数据库名(预留)
|
||||
"DB_NAME": "ai_shiliu",
|
||||
# MySQL 用户名(预留)
|
||||
"DB_USER": "ai_shiliu",
|
||||
# MySQL 密码(预留)
|
||||
"DB_PASS": "",
|
||||
# MySQL 字符集(预留)
|
||||
"DB_CHARSET": "utf8mb4",
|
||||
|
||||
# AI 提供方(openai/deepseek/dify)
|
||||
"AI_PROVIDER": "dify",
|
||||
# OpenAI 接口密钥
|
||||
"OPENAI_API_KEY": "YOUR_OPENAI_API_KEY_HERE",
|
||||
# OpenAI API 基础地址
|
||||
"OPENAI_API_BASE": "https://api.openai.com/v1",
|
||||
# OpenAI 默认模型
|
||||
"OPENAI_MODEL": "gpt-4.1-mini",
|
||||
# DeepSeek 接口密钥
|
||||
"DEEPSEEK_API_KEY": "",
|
||||
# DeepSeek API 基础地址
|
||||
"DEEPSEEK_API_BASE": "https://api.deepseek.com",
|
||||
# DeepSeek 默认模型
|
||||
"DEEPSEEK_MODEL": "deepseek-chat",
|
||||
# Dify 接口密钥
|
||||
"DIFY_API_KEY": "app-a9dofsiQi4e157uDYTx8Lrja",
|
||||
# Dify API 基础地址
|
||||
"DIFY_API_BASE": "http://47.92.48.126/v1",
|
||||
# Dify 用户标识
|
||||
"DIFY_USER": "wechat_user",
|
||||
|
||||
|
||||
|
||||
# 百度 OCR API Key
|
||||
"BAIDU_API_KEY": "ElIQN30iAqpEGi9zv0VlrtQX",
|
||||
# 百度 OCR Secret Key
|
||||
"BAIDU_SECRET_KEY": "7wrO2wDTx7FehuelgG0NCBDFOklnqSz0",
|
||||
# OCR 引擎(baidu/rapid)
|
||||
"OCR_PROVIDER": "rapid",
|
||||
|
||||
# 微信机器人上报后端消息接口
|
||||
"BACKEND_URL": "http://127.0.0.1:5000/api/messages/receive",
|
||||
# 轮询主循环间隔(秒)
|
||||
"BOT_LOOP_INTERVAL": 3,
|
||||
# 点击联系人后等待(秒)
|
||||
"BOT_CLICK_AFTER_DELAY": 1.2,
|
||||
# 切换会话后读取标题等待(秒)
|
||||
"BOT_TITLE_AFTER_DELAY": 1.0,
|
||||
# 联系人切换节流等待(秒)
|
||||
"BOT_CONTACT_SWITCH_DELAY": 1.0,
|
||||
# 主循环异常后的重试等待(秒)
|
||||
"BOT_LOOP_ERROR_DELAY": 3.0,
|
||||
|
||||
# 微信窗口目标宽度
|
||||
"WECHAT_WINDOW_TARGET_WIDTH": 1080,
|
||||
# 微信窗口目标高度
|
||||
"WECHAT_WINDOW_TARGET_HEIGHT": 820,
|
||||
# 微信窗口目标左侧坐标
|
||||
"WECHAT_WINDOW_TARGET_LEFT": 120,
|
||||
# 微信窗口目标顶部坐标
|
||||
"WECHAT_WINDOW_TARGET_TOP": 80,
|
||||
|
||||
# 是否保存 OCR 调试截图
|
||||
"OCR_SAVE_IMAGES": True,
|
||||
|
||||
# 联系人行高(用于定位)
|
||||
"CONTACT_ROW_HEIGHT": 64,
|
||||
# 联系人列宽(用于定位)
|
||||
"CONTACT_ROW_WIDTH": 240,
|
||||
# 联系人列表左偏移
|
||||
"CONTACT_LIST_LEFT_OFFSET": 68,
|
||||
# 联系人列表上偏移
|
||||
"CONTACT_LIST_TOP_OFFSET": 82,
|
||||
# 联系人列表下偏移
|
||||
"CONTACT_LIST_BOTTOM_OFFSET": 0,
|
||||
|
||||
# 会话名区域左偏移
|
||||
"SESSION_NAME_LEFT_OFFSET": 48,
|
||||
# 会话名区域上偏移
|
||||
"SESSION_NAME_TOP_OFFSET": 8,
|
||||
# 会话名区域宽度
|
||||
"SESSION_NAME_WIDTH": 140,
|
||||
# 会话名区域高度
|
||||
"SESSION_NAME_HEIGHT": 24,
|
||||
# 会话名 OCR 放大倍数
|
||||
"SESSION_NAME_OCR_SCALE": 4,
|
||||
# 会话名 OCR 额外放大倍数
|
||||
"SESSION_NAME_OCR_EXTRA_SCALE": 6,
|
||||
|
||||
# 聊天区截图左偏移
|
||||
"CHAT_CAPTURE_LEFT_OFFSET": 310,
|
||||
# 聊天区截图上偏移
|
||||
"CHAT_CAPTURE_TOP_OFFSET": 70,
|
||||
# 聊天区截图宽度
|
||||
"CHAT_CAPTURE_WIDTH": 750,
|
||||
# 聊天区截图高度
|
||||
"CHAT_CAPTURE_HEIGHT": 550,
|
||||
|
||||
# 顶部惩罚权重比例
|
||||
"OCR_TOP_PENALTY_RATIO": 0.18,
|
||||
# 顶部惩罚二值化系数
|
||||
"OCR_TOP_PENALTY_BIN_FACTOR": 2.0,
|
||||
# 顶部惩罚颜色系数
|
||||
"OCR_TOP_PENALTY_COLOR_FACTOR": 2.2,
|
||||
|
||||
# 标题 OCR 区域左偏移(保留较大的方案)
|
||||
"TITLE_OCR_AREA_LEFT_OFFSET": 310,
|
||||
# 标题 OCR 区域上偏移(保留较大的方案)
|
||||
"TITLE_OCR_AREA_TOP_OFFSET": 0,
|
||||
# 标题 OCR 区域宽度(保留较大的方案)
|
||||
"TITLE_OCR_AREA_WIDTH": 600,
|
||||
# 标题 OCR 区域高度(保留较大的方案)
|
||||
"TITLE_OCR_AREA_HEIGHT": 70,
|
||||
}
|
||||
|
||||
|
||||
def _raw_value(key: str) -> Any:
|
||||
env_value = os.getenv(key)
|
||||
if env_value is not None:
|
||||
return env_value
|
||||
return DEFAULT_CONFIG.get(key)
|
||||
|
||||
|
||||
def get_str(key: str, default: str = "") -> str:
|
||||
value = _raw_value(key)
|
||||
if value is None:
|
||||
return default
|
||||
return str(value)
|
||||
|
||||
|
||||
def get_int(key: str, default: int = 0) -> int:
|
||||
value = _raw_value(key)
|
||||
if value is None or value == "":
|
||||
return default
|
||||
return int(value)
|
||||
|
||||
|
||||
def get_float(key: str, default: float = 0.0) -> float:
|
||||
value = _raw_value(key)
|
||||
if value is None or value == "":
|
||||
return default
|
||||
return float(value)
|
||||
|
||||
|
||||
def get_bool(key: str, default: bool = False) -> bool:
|
||||
value = _raw_value(key)
|
||||
if value is None:
|
||||
return default
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
normalized = str(value).strip().lower()
|
||||
if normalized in {"1", "true", "yes", "on"}:
|
||||
return True
|
||||
if normalized in {"0", "false", "no", "off"}:
|
||||
return False
|
||||
return default
|
||||
Reference in New Issue
Block a user