ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Jev Assistant v1.3 技术方案深度解析:三路 API 自定义、本地知识库上下文注入与无障碍截屏 OCR 采集

Jev Assistant v1.3 技术方案深度解析:三路 API 自定义、本地知识库上下文注入与无障碍截屏 OCR 采集 AI 应用大模型交互助手RAG【免费下载链接】jev-chat-jarvis装在手机上的对话副驾在 QQ / X / 飞书里读懂对方、给出候选回复、一键填入输入框发不发由你。非侵入只读屏幕不 hook 不改包。项目地址https://gitcode.com/gh_mirrors/je/jev-chat-jarvis点击查看免费下载本文基于仓库内 docs/v1.3-plan.md 总方案文档结合 docs/v1.3-morning-checklist.md 与当前仓库源码app/src/main/java/com/jev/probe/展开。Jev Assistant 是一款只读屏幕、绝不自动发送的 Android 对话副驾它在 QQ / X / 飞书里读懂对方、给出候选回复、由用户一键填入输入框。v1.3 版本的核心命题有三把判断 / 回复 / 视觉三路模型接口全部做成可配置并带连通测试、引入本地知识库与联系人关联上下文、为读不到控件树的 App 提供截屏 OCR 采集通道。读完本文你将完整掌握 v1.3 的配置契约、知识库数据模型与检索规则、OCR 分层与截屏防连射机制以及每一阶段的验收标准。一、v1.3 要解决什么问题四大目标与阶段编排v1.3 总方案为一次多阶段升级目标拆为四条原文逐条保留API 自定义判断 / 回复 / 视觉三路接口的地址、密钥、模型全部可配带预设与各自连通测试。知识库 关联上下文用户可维护本地知识库笔记 联系人档案每次分析自动带上对该联系人的历史记录与相关知识回复与知识库一致联系人跨 App 关联别名。OCR 采集读不到控件树的 App飞书正文、任意未适配 App走截屏 OCR已适配 App 树读空时 OCR 兜底。版本与发布版本号升到 1.3出 release 包README 更新。阶段顺序与依赖被严格固定为AAPI→ D知识库 / 上下文→ BOCR→ C文档 / 发布每个阶段由一个执行 agent 顺序做完、构建通过再进下一阶段方案文档特别强调同一时间只有一个 agent 改代码gradle 与文件都会冲突。每阶段结束后需写_reports/v13_阶段_report.md内容固定为改了什么逐文件→ 构建输出末尾原文 → 装机结果 →自验缺口。二、硬约束隐私与兼容的红线v1.3 沿袭项目既有约束并新增三条方案原文绝不自动发送、不碰钱、密钥不落盘不进日志不进 git、UTF-8、禁 git commit/push。所有用户数据知识库、联系人、历史记录只存 App 私有目录提供清空按钮聊天正文不进 logcat。旧配置必须自动迁移升级后原来的 OpenRouter 密钥、回复模型、关系描述、白名单、透明度、开关全部保留可用。技术栈约束传统 View XML不引 Compose不引 Room用 JSON 文件 内存缓存即可ML Kit 只在 B 阶段引入。从源码看这些约束是真实落地的KbStore.clearAll()只删除filesDir/kb目录源码注释明确API keys, whitelist and every other SharedPreferences value are untouched聊天正文从不进日志——ChatCaptureService.kt 中连调试日志都只打印side 文本长度。三、公共契约Prefs 配置字段全表v1.3 的第一份公共契约是Prefs 新字段A 阶段建、后续阶段只读。以下字段、默认值与说明均继承自方案文档并已对照源码 Prefs.kt 逐一核实3.1 判断接口Jev字段类型默认值 / 说明judgeProviderStringopenrouter \| typesafe \| custom默认openrouter。从当前仓库源码看实际取值集合已扩展为bocha / openrouter / typesafe / vercel / zen / customPrefs.PROVIDER_*常量judgeBaseUrlStringopenrouter 默认https://openrouter.ai/apitypesafe 默认https://api.typesafe.aijudgeKeyString迁移老openRouterKey→judgeKeyjudgeModelStringopenrouter 默认typesafe/jev-1.13typesafe 默认jev-latest判断接口的请求路径规则方案原文 Prefs.kt 的judgeEndpoint()实现一致openrouter → {judgeBaseUrl}/alpha/decisions typesafe → {judgeBaseUrl}/v1/systemone custom → 用户填完整 URL 到 judgeBaseUrl原样 POST请求体三者相同{model, state, questions}。源码中还加入了同为 TypeSafe 兼容协议的bocha / vercel / zen三个网关均走/v1/systemone它们的 base/model 预设也在 Prefs.kt 的 companion 常量中。3.2 回复接口任何 OpenAI 兼容 chat completions字段类型默认值 / 说明replyBaseUrlString默认https://openrouter.ai/api/v1填到/v1为止客户端自己拼/chat/completions源码replyEndpoint()正是如此拼接replyKeyString留空 用 judgeKey源码effectiveReplyKey()replyKey.ifBlank { judgeKey }replyModelString老字段沿用默认deepseek/deepseek-chat-v3.13.3 视觉接口OCR 用OpenAI 兼容支持 image_url字段类型默认值 / 说明visionBaseUrlString默认同 replyBaseUrlvisionKeyString留空 用 replyKey → judgeKey源码effectiveVisionKey()visionKey.ifBlank { effectiveReplyKey() }visionModelString默认qwen/qwen2.5-vl-72b-instructOpenRouter 区域可用用户可改3.4 上下文与 OCR 开关后续阶段写入字段类型默认值 / 说明contextEnabledBoolean记录历史并注入。修订后默认 false隐私优先不落盘除非用户主动开contextHistoryCountInt注入最近多少条历史默认30源码注入时coerceIn(0, 100)autoSummaryBoolean联系人自动摘要默认true修订后功能推迟ReplyClient.summarize()保留但不接线ocrEngineStringmlkit \| vision默认mlkitocrForUnknownAppsBoolean未适配 App 走通用 OCR默认trueocrFallbackBoolean已适配 App 树读空时 OCR 兜底默认trueocrAutoAnalyzeBooleanOCR 模式自动分析默认false手动点3.5 旧配置自动迁移一次性、可复现方案修订明确三条迁移纪律A 阶段补充迁移只做一次、judgeKey被用户清空不得复活、旧存储名一个不改。源码 Prefs.kt 的migrateIfNeeded()精确实现以prefs_migrated_v13true布尔标记为闸门写过标记后不再读openrouter_key仅当judgeKey为空且老openrouter_key非空时才把老密钥拷到judgeKey并打日志prefs migrated judgeKey.lenN只记录长度绝不记录密钥本身replyModel沿用旧存储键天然继承无需处理老代码的openRouterKey读写保留为judgeKey的兼容别名旧调用点无需改动即可编译运行。四、模型客户端拆分一条链路上三个专职客户端方案将原来臃肿的JevClient拆成四个文件A 阶段职责如下与源码逐一对应jev/JudgeClient.kt // 只管 Jevjudge(snapshot, context) / rank(candidates) jev/ReplyClient.kt // 只管生成draft(snapshot, context) → 3 条summarize(text) → 摘要D 用 jev/VisionClient.kt // 只管视觉extractDialog(bitmap) / ocrLines(bitmap)B 用A 阶段只建壳 jev/HttpJson.kt // 共用的 POST JSON 退避 错误归类把现在 JevClient 里的 postJson 抽出来旧JevClient删除或改成薄门面调用方ChatCaptureService、SettingsActivity 连通测试改用新类。4.1 错误信息规范一路一码一摘要错误信息必须带哪一路 HTTP 状态码 前 120 字响应。源码 HttpJson.kt 用三个要素落实Route常量区分三路判断接口/回复接口/视觉接口ApiException(route, status, snippet)的buildMessage()生成$route HTTP $status${snippet.take(120)}无状态码则为$route 请求失败…传输层错误被describe()翻译成人话网络超时、域名解析失败、无法连接、HTTPS 证书校验失败等且密钥材料绝不进入任何错误文本。4.2 重试策略HttpJson.post()最多 3 次尝试仅对429 / 529服务繁忙做指数退避500ms * (1L shl attempt)其他 4xx 客户端错误一律不重试直接抛出读响应体前先分支状态码保证 401 这类错误绝不会因为读 body 异常而丢失状态码被误判成传输失败。4.3 视觉请求的坑位方案修订 源码注释双重印证方案修订与 VisionClient.kt 源码注释共同列出的三个真花过调试时间的细节图片用data:image/jpeg;base64,前缀Bitmap → JPEGBase64.NO_WRAP避免换行破坏 data URL选 JPEG 而非 PNG截图 PNG 的 base64 体积会大数倍图片 part 必须放在文本 part 之前——通义 DashScope compatible-mode 对相反顺序会直接拒绝DeepSeek 官方不支持 image_urlVisionClient.supportsVision()对api.deepseek.com返回 false测试时要提示该接口不支持视觉。同时视觉 baseUrl 固定走 OpenRouter 默认、不跟随回复接口回复接口切到 DeepSeek 会静默弄坏 OCR故故意不继承。4.4background/history字段的兼容策略D 阶段要给 Jev 的 state 新增background背景知识与history历史消息字段但方案不确定线上alpha/decisions是忽略新字段还是返回 400。因此 JudgeClient.kt 实现了降级重试带背景/历史请求若收到 4xx去掉这两个字段原样重发一次保证新字段可以拖累质量但绝不能打断分析。题目英文 instructions 还补了一句 facts in background are given context, not off-topic排序题同理防止模型把背景事实误判为跑题。五、知识库与关联上下文D 阶段5.1 数据模型存放位置方案原文context.filesDir/kb/notes.json、kb/contacts.json、kb/logs/contactId.json。数据模型与源码 KbModels.kt 完全一致Note(id, title, content, tags: ListString, alwaysOn: Boolean, enabled: Boolean, updatedAt) Contact(id, name, aliases: ListString, apps: ListString, relationship: String, notes: String, autoSummary: String, summaryAtCount: Int, updatedAt) LogEntry(side, text, ts, app) // 每联系人一个文件最多保留 300 条按 (side,text) 去重追加 ChatContext(contact: Contact?, history: ListLogEntry, notes: ListNote, budgetChars 1500)要点Contact.apps记录来源包名如com.tencent.mmaliases就是跨 App 关联的机制——同一个人在微信/QQ/飞书里标题不同全部登记为别名即可命中LogEntry每联系人最多300 条源码KbStore.MAX_LOG 300超限从头部移除。5.2 存储实现JSON 文件 原子写方案修订要求JSON 文件单写者synchronized 原子写临时文件再 rename清空只删filesDir/kb不动密钥与白名单。源码 KbStore.kt 全部落实所有读写走同一个lock对象synchronized单写者由构造保证writeAtomic()先写*.tmp再renameTo目标文件——POSIX 同目录 rename 一步替换进程被杀也不会留下半个 JSONrename 失败才退化为原地覆盖并打日志说明非原子解析损坏的 JSON 文件时先改名备份再当作空库绝不静默覆盖用户数据readJsonArray的trustworthy标记内存缓存 落盘双份写失败即清缓存强制下次回源序列化手写org.json不引 Gson/Moshi呼应不引 Room的轻量约束。5.3 名称规范化与联系人匹配方案修订去首尾空白、零宽字符、群名尾部(数字)、大小写不敏感后再匹配 name / aliases。源码KbStore.normalizeName()正是四步流水线stripZeroWidth正则剔除\u200B-\u200D与\uFEFF→stripTrailingCount正则剥掉半角/全角括号包裹的数字尾巴如测试群(12)/测试群12都归一为测试群→ trim → lowercase。findContact(title, app)命中规则会话标题 contact.name 或 ∈ aliases多个联系人同时命中时优先选已记录过该包名的那个。联系人绝不自动建档修订后只由用户手建或在悬浮窗菜单里把当前会话存为联系人一键建源码KbStore.saveOrMergeContact()已存在的同名联系人会并入包名与别名不产生重复档案。5.4 笔记检索只做两层方案修订把初版中文字符二元组重合度打分收窄为两层朴素规则源码 ContextBuilder.kt 原样实现alwaysOn笔记全带单独占预算、不截断其余笔记按「标签 / 标题 ∈ 会话标题或最近 6 条消息」的包含匹配命中才带最多 5 条MAX_HIT_NOTES 5新笔记优先。总预算budgetChars 1500超预算时先丢弃最旧的历史、再丢最后命中的整条笔记绝不截断半条笔记。5.5 历史记录与去重历史只在contextEnabled且命中联系人时记录opt-in默认关每次采集把当屏消息追加进该联系人的日志文件最多保留 300 条注入前去掉屏幕上已可见的副本只删与当屏消息(side, text)完全相同且长度 ≥ 4的副本DEDUPE_MIN_LEN 4避免把嗯好这类短文本误判为同一句appendLog()以整屏序列为单位做增量去重与上一屏完全相同则不写、日志尾部与当前屏前缀重叠则只追加新滚动出来的尾部、往回翻旧消息则整轮跳过——这是防止滚动采集把历史写重写的核心机制。5.6 注入方式与提示词Jev 的 state 增加background关系 联系人备注 自动摘要 命中笔记与history去掉屏幕上已有的历史消息二者皆空时不发送字段ChatContext.isEmpty()回复提示词固定追加「以下是关于我和对方的背景与知识库回复必须与之一致可以直接引用其中事实不要编造知识库里没有的事实」——源码 ReplyClient.kt 的knowledgeBlock()原文悬浮窗显示一行知识库 N 条 · 历史 M 条ChatCaptureService里overlay.setContextInfo(ctx.notes.size, ctx.history.size)。5.7 一键自检设置页的「自检」对应 KbSelfCheck.kt用临时笔记 临时联系人 一次性 scratch Prefs不碰用户真实配置跑通六项检查——名称归一化含全角括号群名、联系人别名命中、笔记 tag 命中、当屏去重不回流、旧消息注入、contextEnabledfalse时零注入——结束即清理最后返回自检通过联系人匹配 / 笔记命中 / 历史去重 / 预算注入都正常一行结论。六、OCR 采集B 阶段6.1 分层架构方案原文的分层与仓库实际文件结构一致capture/ocr/ScreenCapture.kt // AccessibilityService.takeScreenshot 封装限频 ≥1s、失败原因枚举、Bitmap 回调 capture/ocr/OcrEngine.kt // interface: recognize(bitmap, region): ListOcrLine(text, bounds) capture/ocr/MlKitOcr.kt // com.google.mlkit:text-recognition-chinesebundled capture/ocr/VisionOcr.kt // 走 VisionClient可返回结构化对话 capture/ocr/BubbleGrouper.kt // OCR 行 → 气泡按行距、左右对齐分组side 按气泡贴左/贴右 capture/GenericOcrAdapter.kt // 任意包名裁掉顶栏有标题的与输入区有 EditText 的中间区域 OCR capture/FeishuAdapter.kt 改造 // 树拿 bubble_content_container 矩形 已读容器判 me每个矩形 OCR 正文v1.3 修订把 B 阶段收窄为只做两件事① 飞书树上bubble_content_container矩形 已读容器判 me对每个矩形做 ML Kit OCR结果里剥掉已读② 通用入口悬浮窗菜单截屏识别一次对任意 App 手动截一次整屏 OCR 并分析——不自动、不按左右判 me/other全部记为 other 并在面板标注未分边。视觉模型 OCR 不进采集主路径。注当前仓库中VisionOcr.kt、BubbleGrouper.kt、GenericOcrAdapter.kt尚未落地为独立文件通用整屏分组的实现内聚在 ChatCaptureService.kt 的groupOcrLines()中按行距 1.2× 行高分组面板备注为OCR 未分边把全部消息当作对方所说。6.2 适配器契约三态返回值方案修订把适配器契约拆成三种返回源码 ChatAppAdapter.kt 注释一致extract返回null不在聊天窗列表页、动态页、设置页…服务什么都不做返回ChatSnapshot(messages 为空)在聊天窗但树里没正文——这是 OCR 兜底的唯一触发条件返回非空 messages 正常采集。服务只对第二种走 OCR 兜底且失败退避 1s → 2s → 4s上限 30s绝不每秒连射。当前已接入的适配器为 QQ、X、Feishu微信com.tencent.mm因反截屏风险控制被完全禁用——不读树、不截屏、不 OCR、不填入仅显示一次性提示源码ChatCaptureService的PKG_WECHAT与WECHAT_DISABLED_MSG并有专项注释说明。6.3 截屏实现窗口优先、限频、退避、错误码人话源码 ScreenCapture.kt 对方案修订逐条落地API 34 优先takeScreenshotOfWindow回退takeScreenshot(DEFAULT_DISPLAY)——窗口截屏在分屏/排除状态栏时画面小于整屏且有偏移因此Result.Ok携带scaleX/scaleY/originX/originY节点矩形与 OCR 框按(screenX - originX) * scaleX双向换算截前隐藏悬浮窗HIDE_SETTLE_MS 120ms等一帧让悬浮球消失、截后恢复回调里copy(ARGB_8888)后立刻close()HardwareBuffer——泄漏 HardwareBuffer 会让系统合成器几发之后饿死全局限频 ≥ 1000ms跨实例共享lastAttemptAt因为系统限流是按服务计的连续失败退避1s → 2s → 4s …封顶 30sMAX_STREAK 6回调有 3 秒看门狗超时平台可能对受保护窗口干脆不回调防止悬浮窗永远隐形、忙标志卡死错误码 1/2/3/4/6 各给一句人话humanMessage()1内部错误/系统拒绝2无障碍服务未声明截屏能力去设置关掉再开3间隔太短4没有有效显示6窗口不可见或受保护FLAG_SECURE另有两个自有码 -1 截屏太频繁、-2 截屏超时。6.4 无障碍配置与生效条件无障碍 XML config_disguised.xml 增加android:canTakeScreenshottrue同时保留flagRetrieveInteractiveWindows等采集所需 flags。关键生效条件方案原文写入验收加了该属性后必须把无障碍关掉再开启才生效——HyperOS 不热更新 meta-dataHyperOS 还可能单独拒绝无障碍服务截屏方案明确B 开工第一步先真机打一次takeScreenshot看 errorCode被拒则另起一个截屏专用服务。服务本身以伪装类名com.google.android.accessibility.selecttospeak.SelectToSpeakService注册见 AndroidManifest.xml让微信这类对常规无障碍服务隐藏节点树的应用暴露树——微信最终仍被主动禁用是策略决定而非能力缺失。6.5 飞书适配矩形 已读容器判 me飞书正文是绘制而非 View 布局2026-09-21 真机验证树里几乎永远没有正文文本。因此适配器是混合型源码 ChatAppAdapter.kt树里收集bubble_content_container的屏幕矩形过滤顶栏/输入区带collectFeishuBubbleRects()在截屏回调里重新读取——防抖 隐藏悬浮窗 拍摄之间隔了几百毫秒列表可能已经滚动必须重读避免裁错行边判定不靠几何飞书全员左对齐只有自己的气泡挂已读/发送回执条…time_read_state_container_align_bubble以此判 me对方判 other真机上已读容器判 me属推断项写进了验收的核对点每个矩形做一次 ML Kit OCRcleanBubbleText()剥掉气泡尾部粘着的已读/未读和时间戳。6.6 通用入口截屏识别一次任意未适配 App钉钉、Telegram、微博私信等长按悬浮球 → 「截屏识别一次」整屏截一张OCR 中间区域顶部裁 12%、底部裁到 84%避开标题栏与输入框按行距分组为伪气泡全部记为 other并在面板标注未分边随后照常跑分析。手动触发不受最新消息来自对方门槛限制每次都重新分析自动路径则依赖ocrSignature()飞书用标题 每个气泡矩形及边其他用包名 标题做拍摄前去重——树空时飞书每个 content-changed 事件都会触发兜底没有这道闸门光标闪烁都能变成每秒一张截屏。6.7 ML Kitbundled 中文识别MlKitOcr锁定com.google.mlkit:text-recognition-chinese的bundled非 play-services变体模型打进 APK无 GMS 的手机也能识别、永不联网下载。识别器单例化TextRecognition.getClient(ChineseTextRecognizerOptions.Builder().build())warmUp()在服务连接时于工作线程预载模型避免第一次真识别在主线程截屏回调线程承担模型加载开销坐标从 bitmap 空间经 scale/origin 换算回屏幕空间。方案还要求ndk.abiFilters arm64-v8a、选支持 16KB 页对齐的版本并把包体增量与无 GMS 手机识别一次写进验收项。七、验收标准每阶段构建 装机 真机方案规定的每阶段验收原文完整保留A设置页三组接口各自连通测试通过把回复接口切到 DeepSeek 官方地址再切回QQ 分析仍正常老密钥升级后不用重填。D在设置里建 1 条笔记含一个虚构事实 给某联系人设关系与别名对该联系人分析时候选回复体现该事实日志显示知识库 N 条 / 历史 M 条清空按钮生效。B飞书对话正文被 OCR 读到并分析任选一个未适配 App如钉钉 / Telegram / 微博私信通用 OCR 出候选。CREADME 平台表更新版本 1.3release 包签名校验通过。配套的早间装机清单 docs/v1.3-morning-checklist.md 给出具体操作与预期adb install -r app/build/outputs/apk/debug/app-debug.apk adb shell appops set com.jev.probe SYSTEM_ALERT_WINDOW allow装机后手机上将无障碍关掉再打开新增截屏能力HyperOS 不热更新 meta-data然后看adb logcat -s JEVASSIST是否出现capture service connected与prefs migrated judgeKey.lenNN0 旧密钥迁移成功。真机核对项还包括长按悬浮球「截屏识别一次」出候选 截屏被放行还是内部错误/系统拒绝 HyperOS 拒绝无障碍服务截屏需另起截屏专用服务飞书里我/对方是否判反logcat 不应出现每秒一张截屏签名去重生效。发布门槛versionCode 4 / versionName 1.3、targetSdk保持 35 不抬到 36、assembleRelease apksigner 校验、记录包体清单预期约 27 MB、以apk/jev-assistant-v1.3-release.apk替换 v1.2。八、方案的设计取舍三句话对照 docs/v1.3-plan.md 全文与其修订记录v1.3 的工程取向可以浓缩为三点也是阅读源码时最值得记住的原则隐私是硬约束而非功能密钥只存 App 私有 SharedPreferences、只记录长度不进日志知识库默认不落盘、落盘只写filesDir/kb、清空按钮只删该目录聊天正文从不到 logcat。这解释了contextEnabled修订后默认 false、ocrAutoAnalyze默认 false 等所有默认保守的取值。失败可诊断、降级不崩坏三路错误统一为路由 状态码 前 120 字background/history遇到 4xx 自动降级重发OCR 失败退避封顶 30s 且错误码全部翻译成人话损坏的 JSON 先备份再当空库。能简单就不复杂不引 Compose/Room/GsonJSON 文件 内存缓存 手写 org.json检索不做向量打分只做 alwaysOn 包含匹配排序边判定能省则省通用 OCR 一律 other。方案文档中Grok 4.7 评审后收窄的每一处修订几乎都在往更简单、更保守、更可验证的方向走。以上内容以 docs/v1.3-plan.md 为主体骨架源码实现细节均可在上述各文件路径中核对未真机验证的推断项如飞书已读容器判 me、HyperOS 截屏放行情况在方案与验收清单中均已显式标注为需真机确认与本文保持一致。赞分享AI 应用大模型交互助手RAG【免费下载链接】jev-chat-jarvis装在手机上的对话副驾在 QQ / X / 飞书里读懂对方、给出候选回复、一键填入输入框发不发由你。非侵入只读屏幕不 hook 不改包。项目地址https://gitcode.com/gh_mirrors/je/jev-chat-jarvis点击查看免费下载相关推荐GPT4All本地知识库构建与智能文档分析技术深度解析GPT4All本地知识库构建与智能文档分析技术深度解析 GPT4All作为完全开源的本地大语言模型生态系统在数据私密性和智能文档处理方面展现出卓越的技术优势。人工智能大模型本地部署AI 应用交互助手RAGUmi-OCR中实现自定义文本识别区域的技术方案Umi OCR中实现自定义文本识别区域的技术方案 在OCR应用开发中自定义识别区域是一个较为小众但实用的需求。本文将探讨如何在Umi OCR项目中实现这一功能OCR桌面应用上下文丰富技术为RAG系统注入深度语义理解上下文丰富技术为RAG系统注入深度语义理解 本文详细探讨了RAG系统中的上下文增强技术包括文档级和章节级上下文分块、相关片段提取、语义分块以及上下文压缩等关示例工程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表