Files
crawler-plugin/backend-java/src/main/java/com/nanri/aiimage/config/SimilarAsinProperties.java
T

172 lines
7.5 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.nanri.aiimage.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
@Data
@ConfigurationProperties(prefix = "aiimage.similar-asin")
public class SimilarAsinProperties {
/**
* P0-1:单次提交 LLM 批次的 row 数量。
* 历史值 10,在含 puzzle 多图行的场景下频繁触发 720712008
* "node executed out of limit: 1000"。降到 3 以避免节点上限被打爆。
* 出现持续 720712008 时还会被 P1-1 滑窗自适应再降到 1。
*/
private int llmBatchSize = 3;
/**
* img_switch=false 时单次提交 LLM 的 row 数。
* 不走图片检测时压力小,恢复到 10 行一批以提高吞吐;开启图片检测时仍使用 llmBatchSize。
*/
private int llmTextOnlyBatchSize = 10;
private long dbTaskTouchIntervalMillis = 120000L;
private long dbJobTouchIntervalMillis = 60000L;
private int staleTimeoutMinutes = 30;
private String staleFinalizeCron = "0 */2 * * * *";
/**
* 末尾零头 batch 的强制 flush 阈值(分钟):当不足 llmBatchSize 的零头 row
* 长时间挂着(Python 慢回传)时触发提交。
* 任务级实测:345 行 / 4h 总耗时中,约 2-3 小时是 batch 永远凑不满 batchSize 在等下一波回传,
* 把阈值从 15 调到 1:最多 60s 后 1-2 行也强制提交,让 LLM 提交侧持续进票,
* 总耗时降到与 Python 回传节奏接近。
*/
private int llmFlushPendingMinutes = 1;
/**
* 图片下载、解码和缩放共享该池;4 核生产机默认 2,避免图片任务占满整机 CPU。
*/
private int imageDownloadPoolSize = 2;
/**
* 单张图片下载超时(秒)。
* P2-10:放宽到 8 + retry=1 在快源(aiproxy/m.media-amazon)下没问题,
* 但慢源(cbu01.alicdn)会一直挂 8s 才进入 retry,整体串行时间放大。
* 调到 5s + retry=2,让慢源更早重试新连接,单图最坏耗时 ≈ 5s * (1+2) = 15s。
*/
private int imageDownloadTimeoutSeconds = 5;
/** 单个结果文件整批图片预取预算,耗尽后缺图单元格降级为 URL。 */
private int imagePrefetchTimeoutSeconds = 1800;
/** 多源结果文件组装的单任务硬上限;运行期间由文件任务 heartbeat 保活。 */
private int resultFileTimeoutMinutes = 90;
/**
* Assemble each source workbook from chunk-scoped result maps. Keeping a
* switch makes rollback possible for an existing deployment while the new
* bounded path is observed in production.
*/
private boolean boundedResultAssemblyEnabled = true;
/**
* assemble 阶段 taskImageCache 的字节上限。
* 默认 256MB5000 行 × 3 列 × 平均 100KB = 1.5GB 远超 2GB 堆,
* 用 BoundedImageCache 按字节累计 LRU 淘汰避免爆堆。
* 由于 embed() 写完即 remove(),活跃图片字节通常 ≤ 100MB,仅在极端 prefetch 领先场景才会触发淘汰。
* 出现淘汰过频影响命中率时可上调到 512MB;2GB 堆约束下不建议超过 768MB。
*/
private long imageCacheMaxBytes = 256L * 1024L * 1024L;
private String imageLocalCacheDir = "";
private boolean imageDbCacheEnabled = false;
/**
* 是否启用 merge 增量缓冲:每个 batch DONE 时仅缓冲 llmRows
* 不立即合并到 chunkfinalize 前一次性按 chunkScopeHash 分组合并,
* 把 OSS chunk 读写从 1000+ 次降到 chunk 数量级。
*/
private boolean llmResultBufferEnabled = true;
/**
* 解析接口返回的预览行/预览组数量上限。
* 响应体只携带预览行(默认 100),全量行仅写入后端任务载荷。
* 有效范围 [1, 1000]0/负值回退默认,超上限 clamp 到 1000。
*/
private int parseResponsePreviewLimit = 100;
/**
* Task 7:单个源文件大小上限(字节)。超过则拒绝解析,防止无界文件增长。
*/
private long maxSourceFileBytes = 50L * 1024L * 1024L;
/**
* Task 7:单次解析最大有效行数。超过则拒绝解析,防止任务无界增长。
*/
private int maxParseRows = 50000;
/**
* Task 7:单字段最大长度(字符)。超过的字段值截断到该上限,防止内存无界增长。
*/
private int maxFieldLength = 2000;
/**
* Task 8xlsx(zip) 最大条目数。受控读取在 WorkBookFactory 打开前探测,
* 超过则拒绝,防止 zip bomb / 超大工作簿拖垮内存。
*/
private int maxWorkbookZipEntries = 20000;
/**
* Task 8xlsx(zip) 解压后总字节数上限。同样在打开前探测,超过则拒绝。
*/
private long maxWorkbookUncompressedBytes = 512L * 1024L * 1024L;
/**
* Task 13:单次 chunk 合并后的最大行数。mergeChunkPayload 合并后总行数超过该上限时,
* 从最旧行开始降级到 orphan 兜底(assemble 阶段 putIfAbsent 合并回结果),chunk 不无界增长。
* 默认与 maxParseRows 一致(50000)。
*/
private int chunkMergeMaxRows = 50000;
/**
* Task 13:单次 chunk 合并后 payload 的字节上限。合并后序列化字节超过该上限时,
* 从最旧行开始降级到 orphan 兜底;单行本身超过该上限时抛异常拒绝合并。
* 默认 16MB50000 行 × 平均 300B/行 ≈ 15MB,留余量。
*/
private long chunkMergePayloadMaxBytes = 16L * 1024L * 1024L;
/**
* Task 15:图片缓存 last_used_at 异步批量刷新的缓冲阈值。
* lookup 命中先入内存缓冲(按 url_hash 去重),达到该阈值时立即批量 touch;
* 其余由定时 flush 兜底,把逐图 UPDATE 合并为批量 UPDATE。
*/
private int imageCacheTouchFlushThreshold = 1000;
/**
* Task 16:图片预取短预算(秒)。assemble 阶段预取在预算内 best-effort
* 尽力完成,预算耗尽即取消在途任务并回退 URL,避免整批预取拖垮结果组装。
* 该值仅作用于 assemble 阶段预取;后台预热仍使用 imagePrefetchTimeoutSeconds。
*/
private int imagePrefetchBudgetSeconds = 60;
/**
* 货源查询直连 LLM 模式开关(默认 true:新任务与存量 PENDING 批次都走直连 LLM
* 不再经过工作流中转)。
*/
private boolean directLlmEnabled = true;
/** 直连 LLM 的 base urlOpenAI 兼容 /v1/chat/completions)。 */
private String llmHost = "https://ai.t8star.org";
/** 直连 LLM 的 Bearer token;前端未传 api_key 时兜底使用。 */
private String llmApiKey = "";
/** 类目匹配(一级/二级)使用的小模型。 */
private String llmCategoryModel = "glm-5.3-flash";
/** 合规检查(is_conform/reason/category)使用的小模型。 */
private String llmConformModel = "glm-5.3-flash";
/** 图片相似度对比(主图 vs 拼接图)使用的模型。 */
private String llmImageCompareModel = "glm-5.3-flash";
private int llmMaxTokens = 64000;
private int llmConnectTimeoutMillis = 10000;
private int llmReadTimeoutMillis = 180000;
private int llmRetryTimes = 3;
/** 批内行级并发上限:每行最多 2 次图片对比 + 1 次合规 + 3 次类目匹配。 */
private int llmRowConcurrency = 5;
/** 拼接图/主图下载超时(秒),慢源图片较多时放大该值。 */
private int llmImageDownloadTimeoutSeconds = 10;
}