# 视野后端配置 server: address: ":18080" openapiPath: "/api.json" # 请求体上限(默认 8MB):APK 上传(管理端下发新版本)可能数百 MB,必须放大 clientMaxBodySize: "512mb" database: default: type: sqlite # SQLite 数据文件(运行时数据,不提交 git) link: "sqlite::@file(./data/observer.db)" cache: # 查询缓存 TTL(秒) ttl: 30 auth: # 登录 token 签名密钥(HMAC-SHA256,必填):换值即全员下线 secret: "changeme-auth-secret" # 登录 token 有效期(秒),默认 30 天 tokenTtl: 2592000 admin: # 后台管理端静态 token:请求头 X-Admin-Token 必须匹配;为空时管理接口全部拒绝 token: "Tongli686^*^" app: # Android APK 上传目录(运行时数据,与 ./data 平级、docker-compose 挂载持久化; # 目录下永远只保留最新一个文件 observer-latest.apk,下载地址固定 /download/observer-latest.apk) apkDir: "./workspace" # 模型训练体系运行时数据根目录(图片/标注/模型/训练产物;与 apkDir 同目录时共用 workspace) datasetDir: "./workspace" # 图像生成(管理端「AI 生成图片」):provider 必填项缺失时生成接口返回「图像生成服务未配置」 imageGen: provider: localai # dashscope | localai baseUrl: "http://192.168.3.210:18080" # localai 必填:训练机 local-ai 地址(/v1/images/generations) model: z-image-turbo # localai 上加载的模型名;dashscope 用 qwen-image-3.0 apiKey: "" # dashscope 必填:DashScope API Key timeoutSeconds: 600 # 每张生成超时(默认 120;z-image-turbo 首次加载含模型入显存,稳态秒级~分钟级) # 通用提示词模板(管理端填「动物名称」时启用,每张随机取池组装):{species} 优先用表单填写的名称, # 未填则按数据集名取 speciesByDataset 池(再未配置直接用数据集名);{count} 为数量词(固定 "1只",每张仅 1 个目标;原表单 # 数量选择已取消);{scene}/{action}/{light} 池内随机;物种只写名字不写羽毛细节 # (细节会把镜头拉近,详见技术设计)。不带拍摄角度描述(2026-08-28):角度描述会与目标位置耦合, # 仰拍使贴地目标沉底、固定俯拍构图单一——交由模型平视先验自由构图,目标自然落在中部/上部 promptTemplate: "野外大远景实拍:广角镜头下{scene},{distanceWord}有且仅有{count}{species}的小小身影{sizeHint}在{action},{species}离镜头很远,只是很小的深色轮廓,隐约可辨,画面绝大部分是{scene},没有任何靠近镜头的动物,{light},写实野外摄影,真实照片质感" speciesByDataset: # 数据集名 → 物种池(表单未填动物名称时随机取一个) 鸽子: [家鸽,火斑鸠,虎纹斑鸠,珠颈斑鸠,灰斑鸠] 雉鸡: [雉鸡] 兔子: [兔子] 鸭子: [野鸭] 鹌鹑: [鹌鹑] scenes: # 环境场景池(统一远景原则:每条含开阔/延伸向远方/地平线元素, # 把地平线推开、消除近拍暗示;同一短语在模板中出现两次,须两处都读得通) - "一望无际的玉米地,玉米秆两米多高,田间土路和田埂延伸向地平线" - "一望无际的金黄麦茬田,收割后一直铺到地平线" - "乡村土路穿过广阔的农田伸向远方,路边杂草丛生" - "广阔的农田和道路延伸向远方,一根细电线横贯画面远处" - "广阔田野间一棵高大的树,四周的农田一直延伸到地平线" - "村边开阔的打谷场延伸向远方,尽头是零星的农舍" - "收割后的稻茬田一望无际,铺向远处的村庄" - "果树成行的果园延伸向远方,树下是剪短的草地" - "开阔的沙石滩地和蜿蜒的乡间水渠延伸向远处的田野" - "长满枯黄荒草的田埂和弃耕地延伸向远方" actions: [觅食, 走动啄食, 低头啄食, 踱步, 停落休憩] lights: [清晨柔和阳光, 正午明亮天光, 傍晚金色斜阳, 阴天柔和散射光] sceneByDataset: # 数据集名 → 场景池(按动物习性配置,未配置的数据集回退通用 scenes; # 每条仍含「延伸向远方」元素,且同一短语在模板中出现两次须两处都读得通) 雉鸡: - "田边茂密的草丛和矮灌丛连绵延伸到远方" - "荒草坡和灌木丛连成一片,一直铺向远处地平线" - "收割后的农田边缘杂草丛生,矮灌丛点缀延伸到远方" 兔子: - "枯黄的草坡和荒草地一直延伸到远方" - "弃耕地和田埂长满野草,延伸向远处的林地" - "草丛和矮灌丛交错的荒地,向远处延展" 鸭子: - "宽阔的池塘水面延伸到远方,岸边芦苇丛生" - "水田和浅滩连成一片,水面延伸到远处" - "河湖水面平展到远方,岸边是泥滩和杂草" 鱼: - "清澈的池塘水面下,水草和沙底延伸到远处" - "河流浅滩水域,水底砂石和水草延伸到远方" - "湖水清澈见底,水下的景色延伸到远处" 鹌鹑: - "茂密草丛的田野,草层延伸到远方" - "稻茬田边草丛和荒地相连,延伸向远处" actionByDataset: # 数据集名 → 动作池(按动物习性;动作词不得以「在/于」开头,模板为「在{action}」) 雉鸡: [低头啄食, 草丛中觅食, 踱步, 停歇理羽, 警觉张望] 兔子: [低头啃食草叶, 警觉地竖起耳朵, 小步跳跃前行, 蹲坐不动, 啃食草叶] 鸭子: [缓缓游动于水面, 低头潜入水中觅食, 水面梳理羽毛, 缓慢划水前行, 岸边泥滩觅食] 鱼: [缓慢游动, 贴着水底游动, 水草丛间穿行, 静止悬浮, 缓慢觅食] 鹌鹑: [低头啄食, 草丛间觅食, 小步疾走, 停歇不动] # 目标尺寸提示(sizeHint):按「体高 × focalPx ÷ 表单距离」算出目标在图中的像素高与占比, # 注入模板 {sizeHint}——把「厘米」换算成「米」再参与投影公式;focalPx = 图高/2 ÷ tan(vfov/2) assumedVfovDeg: 52 # 镜头垂直视场角(度),固定为手机默认主摄(2026-08-28 用户定案; # 曾随机 [15,90]、曾试超广角 90,均已否决);体高按物种查 speciesHeights speciesHeights: # 物种站高(厘米,垂直尺度:鸟=脚底到头顶、兽=蹲坐高度、鱼=背到腹); # 与「高度」像素描述及检测框高(≈站高)自洽,勿用体长(体长是水平尺度); # 未配置的物种代码兜底 35cm 家鸽: 20 珠颈斑鸠: 20 灰斑鸠: 18 火斑鸠: 15 虎纹斑鸠: 18 野鸡: 55 兔子: 35 野鸭: 35 鹌鹑: 12 # 训练通道(并发度 1:GPU 独占,同时仅一个 running 任务): # mode=subprocess 训练机与服务器同机;mode=ssh 异机(训练脚本/数据集经 ssh 通道同步) training: mode: ssh # subprocess | ssh ssh: host: "192.168.3.210" # 训练机地址(mode=ssh 必填) user: "root" port: 22 privateKeyPath: "" # 私钥路径与 password 二选一 password: "123" workdir: /opt/pheasant_data # 训练机工作目录(train_server.py / yolov8n.pt 所在) venvPython: /opt/pheasant_data/venv/bin/python datasetDir: datasets # 训练机数据集根目录(相对 workdir,yolo/ 为子目录) timeoutMinutes: 240 # 训练超时判死(started_at 起算;实测 100 张约 3 分钟,千图级约 1 小时) imgsz: 704 # 训练/导出分辨率(须与 App 端推理输入对齐) epochs: 150 # 训练轮数(patience 30 早停,设大可自动停) batch: 16 # 批大小(按训练机显存调整) device: "0" # GPU 编号(cpu 用 cpu) # RF-DETR 预标注服务(管理端标注工作台):需从服务器可达,未配置时预标注接口返回「标注服务未配置」 localAi: baseUrl: "http://192.168.3.210:18080" # 如 http://127.0.0.1:18080(local-ai 兼容 /v1/detection) model: rfdetr-xlarge vlmModel: qwen3.8-9b # VLM 藏匿位补检模型(qwen3.8-9b+mmproj 多模态);与 z-image 显存互斥,两阶段调度 threshold: 0.08 # 候选置信度阈值(宁多勿漏) confConfirmed: 0.2 # 高于此视为确认(class 0),否则疑似(class 1) overlapThreshold: 0.3 # 重叠去重阈值(交叠/较小框面积,NMS 风格;RF-DETR 同目标常输出一大一小两框,minIoU 比 IoU 更能命中) inputSize: 700 # 提交前整图等比缩放最长边 classNames: [pheasant, suspect] # 标注类别名(写入 data.yaml,随 result.json 存模型 labels) labelTask: # 预标注并发度(逐张调 RF-DETR,缺失或非法时回退默认值) poolSize: 4 # 套餐定价(静态配置,改价 = 改本节点后重启服务;金额单位为分,展示名由 days 派生"N天") plans: - id: day days: 1 price_cents: 1000 - id: week days: 7 price_cents: 5600 - id: month days: 30 price_cents: 18000 payment: # 回调验签/IO 处理并发度(缺失或非法时回退默认值) poolSize: 16 wechat: # 微信支付 APP 支付(APIv3),商户号未配置时接口返回「支付未配置」 appid: "" # 开放平台 AppID mchid: "" # 商户号 apiV3Key: "" # APIv3 密钥 serialNo: "" # 商户证书序列号 privateKey: "" # 商户 API 私钥文件路径(PEM) notifyUrl: "" # 回调地址,如 https://api.example.com/api/v1/payment/wechat/notify alipay: # 支付宝 APP 支付,未配置时接口返回「支付未配置」 appid: "" # 开放平台 AppID privateKey: "" # 应用私钥文件路径(PEM) alipayPublicKey: "" # 支付宝公钥文件路径(PEM) sellerId: "" # 收款方 PID(回调校验 app_id/seller_id 用) notifyUrl: "" # 回调地址,如 https://api.example.com/api/v1/payment/alipay/notify