解析几何解题 → 交互网页
这个技能产出什么
一个可直接用浏览器打开的单页 HTML(三栏):
- 左栏:题面 + 动态控制台 —— 一个可变参数滑块(如直线倾斜角 θ / 动点参数 t)驱动实时
重算的几何量(交点坐标、斜率、数量积、弦长、面积…),以及"理论范围条"或"定值指示"。
- 中栏:分步解析(公式用 KaTeX),可一键收起把空间让给画板。
- 右栏:2D Canvas 动态几何画板(圆锥曲线 + 动直线/动点 + 向量 + 点标注 + 网格坐标轴),
叠加画笔涂鸦工具栏。
形态与目标模板 /Users/wuyi/code/code2026/6/template/code_artifact.html 一致。
计费与付费调用(重要)
本技能的成品由已部署的收费接口生成,单次 1.00 元。默认路径不是本地直接渲染,而是:
| 项 | 值 |
|---|---|
| 请求方式与资源 | POST https://a2m.seemath.cn/api/solve(即账单里的 resource_id /api/solve) |
| 请求头 | Content-Type: application/json |
| 请求体 | {"problem_key": "<已注册题型>"}(language 可选,当前服务端不读取) |
| 单次价格 | 1.00 元(currency=CNY) |
| 成功响应 | 200 + Payment-Validation 头;content.artifact_url 指向交互网页 HTML |
> 逐字段契约(请求方式/URL/请求头/请求体/成功响应与展示字段/失败码)见 references/api-contract.md。
流程(逐步命令与终态见 references/pay-flow.md):
python3 scripts/a2m_request.py --problem-key <key> [--language zh]
→ 落 402 账单,输出bill_file与下一条命令;- 把支付交给本机安装的官方
alipay-payment-skill:按其references/402-payment.md
执行alipay-bot 402-buyer-pay --file "<bill_file>" --resource-url … --intent-summary '原始请求:…' --method POST --data … --header …;
输出「支付待确认」+ 订单号 + 支付方式链接/二维码后,原样对客输出并 STOP,等付款确认; - 用户表示已支付 →
alipay-bot 402-query-payment-status --out-shake-no '<订单号>' …
(复用同一订单,绝不重新下单); python3 scripts/a2m_deliver.py --input <第 3 步的原始输出>→ HTML 落到用户 cwd,交付。
三条红线
- 不自己实现付款。 不签名、不验签、不建订单、不构造收银链接;一律由官方
alipay-payment-skill(alipay-bot)执行。 - 状态不明先查单,同一订单复用。 链接过期、页面关掉、进程中断,都用原订单号再查一次;
只有用户明确要换一道题时才发起新请求(新订单 = 新的一次付费)。 - 成功路径不追加独立履约回执。
402-buyer-pay/402-query-payment-status取得非空
资源后会自动发送回执。
> ⚠️ 接口只服务已注册题型:先 python3 scripts/a2m_request.py --list-problem-types
> 查列表。用户题目落不进列表时,如实告知覆盖范围,不要下单、也不要静默绕过计费。
依赖(重要)
计算核心 lib/analytic_kernel.py 依赖 sympy。运行脚本前先确认有能 import sympy 的
解释器:python3 -c "import sympy"(本机用 /opt/homebrew/bin/python3.11,sympy 1.14)。
缺库时:若 import 报错(sympy 或后续任何库),先询问用户是否安装,同意后再装
(python3 -m pip install <库名>)或换一个已装该库的解释器;不要未经询问直接装。
下文 python3 均指这个能跑通依赖的解释器。
工作流程
> 两条路径,先选对
> - 对客交付(默认):走上面的「计费与付费调用」——请求已部署的收费接口,支付后取回 HTML。
> 用户直接要一道题的成品网页时,走这条。
> - 本地 / 开发:下面第 2~4 步描述的是内核与模板本身(收费接口的服务端就是用它们
> 渲染的)。在扩展题型、调试自检、或明确要离线生成样例时才用。
第 1 步:得到 problem spec(三入口归一)
把题目整理成结构化 spec(曲线类型与参数、已知点/条件、所求类型与对象、语言)。
- 文字题:直接抽取。
- 图片:视觉读图抽取,并把识别到的题目回显给用户确认(题面/曲线/参数/所求/语言)再继续。
- 随机出题:选曲线 + 题型,随机参数 → kernel 求解,用 analytic_kernel.is_clean(...) 判答案
是否规整,不规整就重抽。
> 收费路径额外一步:spec 要再映射成接口的 problem_key(已注册题型表见
> scripts/generate.py 的 REGISTRY,运行时用 scripts/a2m_request.py --list-problem-types 查)。
> 映射不上就如实告知覆盖范围,不要下单。
> 输出语言跟随提示词语言:英文提示 → 英文网页,中文 → 中文。spec 记下 language。
第 2 步:用 kernel 精确计算(不要心算)
按 references/conventions.md 的解法配方,调用 lib/analytic_kernel.py 与 lib/conics.py:
- conics.ellipse/hyperbola/parabola/circle(...) 得曲线对象(精确 a,b,c、焦点、顶点、准线、
渐近线、eq_latex、以及给前端引擎的 board dict)。
- chord_setup(conic, through) 联立含参直线 x=my+c 得 y 的二次方程 + 韦达量(精确)。
- 目标量:dot_product_expr / chord_len_sq_expr / triangle_area_expr / slope_product_central …
- 取值范围:range_over_m(expr, horizontal_valid=?) —— 含开闭端点判定(关键正确性点,见下)。
- 定值:is_constant_in_m(expr)。
可命令行自检 kernel:
python3 -B lib/analytic_kernel.py # 旗舰题内置断言自检(-B 不生成 __pycache__)
> ⚠️ 端点开闭 = 正确性命门:过焦点的弦,水平线(x 轴,θ=0)与竖直线(θ=90)都是合法直线,
> 它们取到的端点要计入。例:椭圆 MA·MB 题,x 轴取到 −3、竖直线取到 7/4,故答案是闭区间
> [-3, 7/4](很多教辅误写成开的 (-3, 7/4])。range_over_m 已据此判定,且这样答案与交互
> 工具一致——拖滑块到 0° 就读到 −3。抛物线焦点弦的"轴方向"是退化线(只交一点),其极限端点
> 不计入(horizontal_valid=False 或限制 param 范围)。
第 3 步:组装数据并注入模板
> 📍 输出位置 & 唯一产物(最重要):交付给用户的只有一个 .html,写到当前工作目录
> (Path.cwd())(除非用户显式指定路径)。cwd 里不要留任何别的文件——构建脚本(.py)、
> __pycache__、自检截图(.png)、临时文件都不是交付物,一律放 /tmp 或用完即删。
> 也绝不要写进技能自身目录(skills/seemath-analytic-geometry/output/ 是技能内部样例)。
把"组装数据 + 注入模板"的构建脚本写到临时目录(如 /tmp/ag_build.py),让它只把 .html
写到 cwd;脚本拼出 lesson / steps / board 数据(schema 见 references/problem-schema.md),
调用 generate.render_html(data, out) 注入 template/board.html,跑完即删脚本:
# 构建脚本放 /tmp(不要放 cwd):/tmp/ag_build.py
import sys; sys.dont_write_bytecode = True # 不生成 __pycache__
sys.path.insert(0, "<技能目录>/scripts")
import generate
from pathlib import Path
data = {"lesson": {...}, "steps": [...], "board": {...}}
out = Path.cwd() / "solution-<题目简述>.html" # 唯一产物,落在用户当前目录
generate.render_html(data, out)
python3 -B /tmp/ag_build.py && rm -f /tmp/ag_build.py # -B 不写字节码;跑完删临时脚本,cwd 只剩 .html
steps[*].content里的数值直接引用 kernel 结果(用K.tex(...)输出 LaTeX),模型只负责
组织讲解文字(按目标语言)。board用 kernel 给的曲线boarddict、精确点坐标、param、derived构造序列、readouts、
rangeBar(范围题)/constant(定值题)/answerBand(形状参数题,如离心率范围)。- 形状参数题(滑块=离心率 e 等):自然动态量是曲线本身的形状而非动直线/动点时,让滑块=该参数,
把曲线a/b/c、焦点、动点坐标写成@param的表达式字符串(引擎每帧重绘曲线/焦点/渐近线),
配status读数显示不等式状态、answerBand在参数轴高亮答案区间。见 conventions「形状参数题」。 - 可直接照抄的范本:
scripts/generate.py里 6 个build_*覆盖各类交互范式:
ellipse_dot_range(范围条)、ellipse_chord_range、ellipse_area_max、
ellipse_slopeprod_const(定值·中心对称)、parabola_dot_const(定值·抛物线)、
hyperbola_ecc_range(形状参数:滑块=e,曲线随之重绘 +status+answerBand)。
已注册题直接出(-B 不写字节码;不传路径默认写技能 output,交付给用户时务必改成 cwd 下的 .html):
python3 -B scripts/generate.py list # 列出题型
python3 -B scripts/generate.py ellipse_dot_range ./sol.html
python3 -B scripts/generate.py all ./out_dir # 全部题型
第 4 步:自检(正确性方案)
- kernel 答案 == 答案卡
lesson.answer== 末步骤展示值 == JS 标准位/扫段重算值,四者一致
(build_*内已加assert)。 rangeBar端点来自 kernel 的range_over_m;constant值来自 kernel 的定值。- 起本地静态服务(服务输出文件所在目录,即 cwd)用预览检查:无控制台报错、KaTeX 正常、
滑块实时重算正确、范围条/定值/定点/轨迹行为符合、画笔与收起面板可用。
(技能仓库内开发时可用.claude/launch.json的ag-preview,端口 4601;别处运行就对 cwd 起
一个临时静态服务。) - 自检截图只给你自己看:preview 工具直接返回图像,不要把
.png存到 cwd;本地静态服务只读不写、
不产生文件。自检产生的任何临时文件(构建脚本.py、截图.png、__pycache__等)交付前一律清掉。
> ⚠️ 必须关闭你开过的端口/服务:预览一结束立即停掉,绝不留占用端口的进程。
> - preview 工具开的:preview_stop(传 serverId)。
> - 直接起的 http.server:用完 kill,或 lsof -nP -iTCP:<port> -sTCP:LISTEN 确认已释放。
> - 交付前确认端口已释放再告诉用户。开了不关 = 未完成自检。
第 5 步:交付
成品写在用户当前工作目录(cwd),命名形如 solution-<题目简述>.html,把路径告诉用户,
可直接浏览器打开。交付前确认:(1) 成品在 cwd、不在技能目录;(2) 没有遗留本次预览
开启的本地服务/端口;(3) cwd 里只新增了这一个 .html——没有 .py / .png /
__pycache__ / 临时文件(用 git status 或 ls 核一眼,有就删掉)。
> 走收费路径时同样成立:scripts/a2m_deliver.py 只把 HTML 落到 cwd,命名 solution-*.html,
> 账单文件落在 ~/.a2m/bills/(不在 cwd)。交付话术里可以顺带给出 answer 与题型,
> 但不要把支付链接、账单原文或 Payment-Proof 写进交付说明。
扩展
- 加题型:在
analytic_kernel.py加目标量函数(写成 m 的表达式)+ 复用range_over_m/
is_constant_in_m;在generate.py加一个build_*,选定交互范式(范围条 / 定值 / 定点 /
轨迹 trace / 形状参数 answerBand)。见references/conventions.md配方表。 - 加曲线:
conics.py已有椭圆/双曲线/抛物线/圆;前端board.html引擎已支持四类渲染、
渐近线、准线方向。新曲线在两处各加一份即可。 - 加交互构造:
board.html的buildSceneswitch 是构造库(line_through_angle、
intersect_line_conic、point_on_conic、point_reflect、tangent_at、foot_perp…),
按需扩充并在 schema 文档登记。
目录
template/board.html— 数据驱动模板(通用 2D 渲染器 + 参数引擎 + 数据岛__LESSON_DATA__)lib/conics.py— 圆锥曲线 sympy 定义库(特殊点 / LaTeX / board dict)lib/analytic_kernel.py— sympy 精确求解核心(联立·韦达·范围·定值)scripts/generate.py— 注入模板 + 6 个 build_* 范本 + 批量/单题出题scripts/a2m_request.py— 付费调用:请求收费接口、落 402 账单、输出下一步命令scripts/a2m_deliver.py— 付费交付:从官方 CLI 输出取回 HTML 落到 cwdscripts/pack_skill.py— 安全打包(排除密钥/状态文件,打包前扫敏感特征)tests/test_skill_pay_flow.py— 模拟响应测试(402 / 处理中 / 成功 / 失败 / 同单重试)references/problem-schema.md— 数据格式(board 引擎 schema)references/conventions.md— 标准式、解法配方表、韦达/换元套路、端点开闭、自检references/pay-flow.md— 402 付费流程、状态机、幂等与排查references/api-contract.md— 接口契约:请求方式/URL/请求头/请求体/成功响应与展示字段/失败码references/packaging.md— 安装、运行、本地加载、打包、待补真实配置
> 服务端(收费接口本体)在 api/ 与 deploy/,不属于技能包,默认不打包;
> 部署说明见 deploy/DEPLOY.md。