ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

k-skill seoul-weather-risk 行政洞解析设计:如何把「행정동 이름 + 자연어」确定性转换为 ASK Seoul 的 place_id

2026/9/17 14:57:49 拓冰建站 浏览量
k-skill seoul-weather-risk 行政洞解析设计:如何把「행정동 이름 + 자연어」确定性转换为 ASK Seoul 的 place_id k-skill seoul-weather-risk 行政洞解析设计如何把「행정동 이름 자연어」确定性转换为 ASK Seoul 的 place_id【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill本文围绕仓库 docs/superpowers/specs/2026-08-09-seoul-weather-risk-admin-dong-resolution-design.md 展开并结合 实施计划、helper 源码、单元测试 与 功能指南 进行纵深讲解。一、设计目标让普通用户不再需要知道 place_idseoul-weather-risk是 k-skill 仓库中面向「서울首尔气象风险」的只读技能它以weather_place_risk_window这一单产品为唯一数据出口返回指定地点在特定时间窗内的 폭염酷暑、한파寒潮、호우暴雨、대설大雪、강풍大风等风险候选时段。该产品在数据契约层面以place_id作为地点主键格式为seoul_admd_10자리 행정동 코드10 位行政洞代码。但普通用户并不知道这一内部 ID。因此本次设计的核心目标是让用户即使不知道place_id也能通过「행정동 이름行政洞名称 자연어 질문自然语言提问」使用该技能。Skill helper 在本地把行政洞名称确定性地解析为 ASK Seoul 的正规place_id再调用既有 hosted proxy 的只读 data 路径。换句话说这是一次「输入层人文化、数据契约零改动」的增强用户层只接触人类可读的地名而下游 proxy 与 ASK Seoul 服务仍然只收到place_id。二、不改变的安全边界设计红线设计文档首先明确划定了「变更边界」这是整套方案安全性的前提原文逐条保留如下目标产品维持weather_place_risk_window单一产品不变不拓宽 hosted proxy 的认证、scope、单产品 allowlist 边界不修改 D1、Worker、Publisher、dbt 模型及 Marketplace 数据契约不新增任意 SQL、fuzzy search、坐标 geocoding、实时位置推断既有--filter place_id...高级用户路径保持向下兼容。从源码看这些边界都有对应实现佐证。例如 seoul_weather_risk.py 中EXACT_PRODUCT_IDS仅包含weather_place_risk_window一个产品bundle 校验函数 会校验 bundle 返回的产品集合与该集合完全一致出现漂移drift时直接以response_contract_invalid契约错误中止对应测试test_bundle_single_product_drift_fails_closed。这正是「单产品 allowlist 不拓宽」的实现证据。三、基准数据与版本427 个行政洞的冻结快照解析所依赖的基准数据来自外部数据管线设计文档给出的关键事实如下项值基准源ASAC-DBTweather_place_grid_mapping.csv基准版本mapping_methodkma_admin_dong_grid_20260325快照规模서울 행정동 427 个唯一place_id427 个place_id格式seoul_admd_10자리 행정동 코드名称重复신사동1 组同名강남구 / 관악구关键约束技能必须携带一份版本冻结的 JSON reference运行时不依赖任何外部仓库或 API。reference 只保存最小字段mapping_version、source、generated_at以及每条记录admin_dong、gu、place_id。仓库中的实际快照位于 seoul-weather-risk/references/admin-dong-place-map.json头部即包含mapping_version:kma_admin_dong_grid_20260325、source:ASAC-DBT/domains/traffic_weather/seeds/weather/weather_place_grid_mapping.csv、generated_at:2026-08-09。数据按place_id排序例如잠실본동송파구→seoul_admd_1171065000신사동分别出现在 강남구seoul_admd_1168051000与 관악구seoul_admd_1162068500两条记录中。reference 的加载与校验实现在 源码_load_location_mapping逐项检查版本号、source、generated_at非空、行数必须等于 427、每行字段集合必须精确为{admin_dong, gu, place_id}且均为非空字符串、place_id必须匹配seoul_admd_ 10 位数字、不得存在重复place_id或重复行政洞, 自治区组合任何违反都以location_mapping_invalid失败。常量LOCATION_MAPPING_VERSION与LOCATION_MAPPING_SIZE定义于 源码第 26-27 行。四、输入契约位置输入「三选一」query命令新增以下可选参数实现在 parser 定义处--admin-dong 행정동명普通用户默认位置输入--gu 자치구명仅用于解决同名歧义必须与--admin-dong同时使用既有--filter place_id정규 ID高级用户与既有调用的兼容路径。互斥规则位置输入只允许「恰好一种方式」。输入组合结果--admin-dong与place_idfilter 同时给出conflicting_location_input失败仅--gu无--admin-donginvalid_location_input失败仅--admin-dong无歧义解析为唯一place_id仅--admin-dong同名歧义ambiguous_admin_dong 候选自治区列表--admin-dong--gu可确认唯一解析为对应place_id源码 run 函数中的校验段 完整实现了这一契约先检查--gu是否伴随--admin-dong再检查两者是否为空串invalid_location_input随后若place_id已存在于 filters 中则抛conflicting_location_input最后调用_resolve_admin_dong并把解析出的正规 ID 写入filters[place_id]。对应的 测试用例 验证了--gu无--admin-dong与冲突输入的失败路径且确保失败时不会把admin_dong、gu字符串泄漏进上游请求参数。五、规范化与解析规则精确匹配优先、安全失败设计文档明确规定了 4 步字符串规范化流程Unicode NFC 规范化去除首尾空白连续空白折叠为单空格仅接受规范化字符串的精确匹配。同时明确不做的事不做后缀去除、不做 초성初声搜索、不做相似字符串匹配、不做自动错别字修正。设计哲学是「宁可安全失败也不查错地点」——错误地返回另一个洞的数据比报错危害更大。源码中对应实现为_normalize_location_namedef _normalize_location_name(value: str) - str: return .join(unicodedata.normalize(NFC, value).strip().split())解析结果矩阵候选情况结果候选 1 个转换为该place_id候选多个、未给--gu返回ambiguous_admin_dong 候选自治区列表候选多个、--gu确认 1 个转换为该place_id候选 0 个unknown_admin_dong--gu未知unknown_gu确定性的书写别名来自 instruction.md 的补充约定虽然「精确匹配」是主路径但韩国行政洞名的书写变体是现实问题。instruction.md 与实现补充了一套可确定性生成的别名规则设计文档未展开、但在最终产物中落地值得完整继承数字前紧邻的제可省略如성수2가제3동→성수2가3동数字分隔点允许「마침표./ 가운데점·/ 省略」三种形式如종로1.2.3.4가동、종로1·2·3·4가동、종로1234가동均可解析到同一 ID除此之外不生成任何别名오타、유사 이름、생활권·통칭、部分名称如성수동一律unknown_admin_dong不做 fuzzy 猜测。实现位于_alias_keys用正则제(?\d)只删数字前的제并枚举./·/省略的组合与_location_indexes建立正名索引与别名索引正名命中优先于别名。测试文件 对每个含제、含.的 reference 行逐一验证所有可生成别名均能带--gu解析成功且제기동这类「非数字前 제」不会被误删기동应报unknown_admin_dong。解析主函数_resolve_admin_dong核心实现位于 源码第 395-424 行逻辑为规范化输入 → 加载并校验 reference → 先查正名索引、未命中再查别名索引 → 候选为空抛unknown_admin_dong→ 若给了--gu则先校验自治区是否已知否则unknown_gu再用自治区过滤候选过滤后为空抛unknown_admin_dong→ 按自治区, place_id排序后若仍多于 1 个则抛ambiguous_admin_dongdetails.candidates带完整候选否则返回唯一记录。测试 test_resolve_admin_dong_requires_gu_for_duplicate_name 验证신사동不带--gu时精确返回 강남구/관악구两个候选。六、错误契约统一的 typed JSON envelope所有新错误码统一走既有 JSON error envelopeexit code 为 2错误码含义invalid_location_input位置输入组合非法如仅--guconflicting_location_input--admin-dong与place_idfilter 冲突unknown_admin_dongreference 中不存在该行政洞ambiguous_admin_dong同名/别名候选冲突details.candidates含自治区与place_idunknown_gu未知自治区location_mapping_invalidreference 缺失、ID 重复或 schema 错误实现上SkillError携带code/message/detailsrun 函数 在捕获后向 stderr 输出{error: {code, message, details}}并返回 exit code 2。这与该技能既有invalid_limit、query_window_unavailable、product_not_ready等错误处于同一契约体系。七、执行流程解析留在本地proxy 边界不变设计文档给出的执行流共 5 步逐条保留helper 照常校验 bundle 与 product metadata 契约在本地 reference中解析--admin-dong用解析结果校验既有公开 projection filter仅向 proxy 发送place_id、时间范围、limit、cursor响应行按既有 data 契约校验后原样输出。由此得到两个关键推论源码均有印证proxy 与 ASK Seoul 服务不承担行政洞字符串解析职责上游请求中只有place_id绝无admin_dong/gu字符串。测试 test_query_maps_admin_dong_to_place_id_before_proxy_request 断言最终 query 精确等于{place_id: [seoul_admd_1171065000], limit: [1]}且不含admin_dong/gu键。无需用户 API Key 的安全模型保持不变helper 不发送Authorization头ASK Seoul 专用服务密钥只存在于 proxy 运行环境。测试 test_query_uses_narrow_proxy_paths_without_user_bearer_auth 断言三次请求的Authorization均为None。进一步地test_disabled_proxy_never_echoes_legacy_user_credentials 验证即便环境变量里存在旧式用户密钥输出中也不会出现它。八、文档与 Agent 行为约定设计文档为 skill helper 的使用方式定下了行为准则最终在 instruction.md 中落地默认示例使用人类可读名称如--admin-dong 잠실본동从自然语言问题中提取行政洞名后原样传给--admin-dong遇到신사동这类歧义时先向用户询问一次自治区收到答复后用--gu重新调用在解释响应时优先使用用户输入的行政洞名与产品的预报时刻、风险依据而非内部place_id。日常快速路径是query --fast见 fast path 设计该路径跳过 bundle/product metadata 往返只调用 data 路由一次同时保留本地行政洞映射、日期与 limit 校验。典型命令如下来自 instruction.mdnpx -y nomadamas/k-skill0 exec seoul-weather-risk scripts/seoul_weather_risk.py -- query --fast \ --product-id weather_place_risk_window \ --admin-dong 잠실본동 \ --from 2026-08-12 \ --to 2026-08-12 \ --limit 100同名歧义场景则追加--gunpx -y nomadamas/k-skill0 exec seoul-weather-risk scripts/seoul_weather_risk.py -- query --fast \ --product-id weather_place_risk_window \ --admin-dong 신사동 \ --gu 강남구 \ --limit 100需要--filter或检查发布契约时才退回 full-contract query先preflight→catalog→describe。日期输入约定--from YYYY-MM-DD扩展为当日00:00:00--to扩展为23:59:59若 ASK Seoul serving window 未覆盖自午夜起全天导致422 query_window_unavailablehelper 会按available_from_at/available_to_at与请求区间求交仅重试一次无交集则返回该错误的 available window 信息并中止实现见 源码_retry_query_after_unavailable_window与测试 test_query_clips_calendar_day_to_available_window。九、验证计划从单元到全量 CI设计文档列出 8 项验证最终在 tests/test_seoul_weather_risk.py 中全部落地잠실본동正确转换为seoul_admd_1171065000并传入 proxy data querytest_query_maps_admin_dong_to_place_id_before_proxy_request首尾/连续空白与 Unicode NFC 规范化test_resolve_admin_dong_normalizes_unicode_nfc、test_resolve_admin_dong_normalizes_internal_whitespaceNFD 输入与 잠실 본동 均解析到同一 ID신사동单独输入以含候选自治区的ambiguous_admin_dong失败test_resolve_admin_dong_requires_gu_for_duplicate_name신사동 강남구收敛为单一 IDtest_resolve_admin_dong_uses_gu_to_disambiguate未登记洞、错误自治区、冲突位置输入均为 typed errortest_resolve_admin_dong_rejects_unknown_or_broad_dong_and_gu、test_query_rejects_*系列既有place_idfilter 调用行为不变回归test_query_uses_narrow_proxy_paths_without_user_bearer_authreference 的 427 行、唯一 ID、版本与必填字段不变量test_admin_dong_reference_has_expected_version_and_unique_place_ids以及损坏 reference 的location_mapping_invalid用例test_load_location_mapping_rejects_invalid_reference源码与 CLI bundled copy 完全同步且整体npm run ci通过由实施计划 Task 5 规定通过npm run generate:skill-stubs -- --check、npm run sync:cli-skills -- --check、git diff --check校验后执行全量 CI。此外测试还覆盖了别名生成的不变量test_resolve_admin_dong_resolves_every_generated_map_alias_with_gu遍历 reference 中每一行生成的每一个别名并断言可解析回原记录test_resolve_admin_dong_does_not_omit_non_numeric_je则防止对非数字前的제误删。十、完成条件与设计价值设计文档定义的完成条件为用户仅凭行政洞名称即可查询非歧义地点的气象风险数据同名地不因缺少自治区而被任意选取proxy 不新增任何 query field 或用户凭证生成桩、CLI bundle、单元测试与全量 CI 全部通过。从仓库现状看该设计已完整落地reference 快照、helper 解析实现、typed 错误契约、单元测试、instruction.md、skill.json 与生成的 SKILL.md 均已就位且packages/k-skill-cli/skills/seoul-weather-risk同步资产由scripts/generate-skill-stubs.js与scripts/sync-cli-skills.js负责生成与校验。这一设计的核心价值在于在零数据契约改动、零安全模型放宽的前提下把「人类可读的行政洞名称」与「机器可查的 place_id」之间的鸿沟用一份 427 行的冻结 JSON 和一段纯标准库 Python 确定性解析逻辑安全地弥合起来——既照顾了普通用户的自然语言输入体验也保住了高级用户的place_id兼容路径同时把「查错地点」的风险降到最低。【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考