RepStack
RepStack是一个 无状态 MCP服务器,将力量训练日志规范化为确定性规范模式。
确实如此 不 存储用户或日志。确实如此 不 持久化数据。确实如此 不 充当分析后端。
消费者负责存储规范输出并在下游构建分析。
RepStack旨在作为规范化层嵌入到更大的健身应用程序中。
______________________________________________________________________
RepStack做什么
- 规范化 将训练日志(CSV、JSON或自由文本)转换为规范模式
- 可选地 使用LLM进行文本预解析(输出仍需经过确定性验证)
- 计算 确定性度量 提供 规范会话或日志
- 提供 练习搜索/注册表查找
RepStack是一个 规范化+确定性计算引擎。所有存储责任属于消费应用程序。
______________________________________________________________________
设计理念
RepStack是确定性的。
- 正则结构 通过模式验证强制执行。
- LLM解析 (可选)仅用于文本提取;LLM输出从不定义规范正确性。
- 所有分析 必须对明确传递给工具的规范会话进行操作(例如。
repstack.compute_metrics随着sessions或logs在有效载荷中)。 - 不确定的匹配 →
exercise_id: "unmapped:";没有模糊自动映射。可以为部分比赛提供候选人。
______________________________________________________________________
快速入门
运行MCP服务器
pip install -r requirements.txt
python -m repstack.server或者在可编辑安装后: repstack
调用摄取工具
对于 文本 可以使用LLM预解析的日志:set content_type: "text" 和 options.allow_llm: true。如果配置了LLM,服务器将使用LLM(请参阅 配置LLM)否则,它会添加警告并回退到确定性解析器。回应包括 meta.llm_available 和 meta.llm_used.
示例有效载荷(CSV):
{
"user": { "default_unit": "lb", "timezone": "UTC" },
"log_input": {
"content_type": "csv",
"content": "exercise,weight,reps\nBench Press,135,5\nSquat,225,5"
},
"options": { "session_date_hint": "2025-01-15" }
}输出形状示例:
status:"ok"|"needs_clarification"|"error"log_id:正常时请求作用域id(客户端可以用作存储密钥)canonical_log:{ "sessions": [ { "date", "exercises": [ { "exercise_id", "sets": [...] } ] } ] }issues:列表{ severity, type, location, message, ... }summary:{ sessions_detected, exercises_detected, sets_detected, confidence }meta:{ "llm_available": bool, "llm_used": bool }(当LLM相关时)
有效载荷示例 文本+LLM:
{
"user": { "default_unit": "lb", "timezone": "UTC" },
"log_input": {
"content_type": "text",
"content": "Bench 135x5 145x4, Squat 225x5x3, RDL 135x8"
},
"options": { "session_date_hint": "2025-01-15", "allow_llm": true }
}调用compute_metrics
在请求中发送规范数据(无服务器端存储):
{
"sessions": [ { "date": "2025-01-15", "exercises": [ { "exercise_id": "barbell_bench_press", "sets": [ { "weight": 135, "unit": "lb", "reps": 5, "load_type": "weighted" } ] } ] } ],
"range": { "start": "2025-01-01", "end": "2025-01-31" }
}或发送 logs:数组 { "canonical_json": { "sessions": [...] } }.
答复: status, range, weekly (体积、吨位、硬设置、旗帜), exercise_summaries, issues (例如。 payload_too_large 如果超过限制)。
______________________________________________________________________
工具合同
工具:repstack.ingrest_log
- 输入:
user(可选user_id,default_unit,timezone),log_input(content_type:"csv"|"json"|"text",content),可选options(session_date_hint,allow_llm,strictness, …). - 输出:
status,user_id,log_id(当ok时),canonical_log,issues,summary,signature,meta(llm_available,llm_used).没有坚持。
工具:repstack.computer_metrics
- 输入: 要么
sessions(规范会话对象数组) 或logs(数组{ canonical_json: { sessions } }).可选的range:{ start, end }(年-月-日)。可选的options(e1rm_formula,包括pr等)。 - 输出:仅限确定性指标:
status,range,weekly,exercise_summaries,issues(例如。payload_too_large),signature.没有用户身份;没有存储访问权限。
工具:repstack.search_exercises
- 输入:
query,可选equipment,movement_pattern,limit. - 输出:
query,count,results随着exercise_id,display,match(策略、分数、匹配文本、规范化查询),is_exact_match.
______________________________________________________________________
MCP表面(仅限工具)
- repstack.news_log --使锻炼日志正常化。返回规范日志、问题、摘要。无国籍。
- repstack.计算机信息 --根据提供的数据计算指标
sessions或logs无国籍;有效载荷尺寸的护栏。 - repstack.search练习 --通过查询查询运动登记;可选过滤器。
有 无MCP资源 (没有 log://,没有 user://).仅限工具。
______________________________________________________________________
配置LLM
LLM是 服务器端 和 提供者不可知:您可以通过env或注册解析器来选择使用哪个提供程序。工具负载无法传递API密钥或提供程序。
选项1:Env--可交换提供程序
集 REPSTACK_LLM_PROVIDER 注册提供商的名称(例如。 openai).当摄取工具首次需要解析器时,服务器将调用该提供者的加载器。
内置提供者: openai
REPSTACK_LLM_PROVIDER=openai(或者保持未设置,只设置下面的键;默认为openai)REPSTACK_OPENAI_API_KEY-您的API密钥REPSTACK_OPENAI_MODEL--可选;默认gpt-4o-mini
需要 openai 包裹: pip install openai 或 pip install repstack[llm].
添加另一个提供者(例如Anthropic、本地模型)
注册一个加载器,读取自己的env并返回解析器(或 None):
from repstack.llm_parser import register_llm_provider, parse_llm_workout_json, WORKOUT_EXTRACTION_SYSTEM
def load_anthropic_parser():
api_key = os.environ.get("ANTHROPIC_API_KEY", "").strip()
if not api_key:
return None
# ... create client, then return a function (content, session_date_hint) -> raw_sessions
# that calls your API and returns parse_llm_workout_json(response_text)
return my_anthropic_parser_fn
register_llm_provider("anthropic", load_anthropic_parser)然后设置 REPSTACK_LLM_PROVIDER=anthropic (以及提供者的env变量)。共享合约是JSON格式 parse_llm_workout_json() / WORKOUT_EXTRACTION_SYSTEM 在 repstack.llm_parser.
选项2:嵌入-- set_llm_parser(fn)
如果你在自己的应用程序中运行RepStack,你可以直接设置解析器(覆盖env):
from repstack.llm_parser import set_llm_parser
set_llm_parser(my_parser_fn) # (content: str, session_date_hint: str | None) -> raw_sessions解析器签名:返回 list[tuple[str | None, list[tuple[str, list[dict]]]]] --每个元组是 (date or None, [(exercise_name, [set_dict, ...]), ...]);每个 set_dict 至少有 weight, reps, unit,并且可选 load_type, added_weight.
______________________________________________________________________
规范数据模型(简化)
每 会话: session_id, date (YYYY-MM-DD), title, notes, 练习\[\].
每 锻炼: exercise_raw, exercise_id (蛇病例或 unmapped:), exercise_display, 集合\[\].
每 集: set_index, reps, load_type (weighted | bodyweight | bodyweight_plus | assisted).对于 weighted: weight, unit.为 bodyweight_plus: added_load: { value, unit }.可选: rpe, set_type, notes.
未映射或不确定的数据报告在 issues,而不是默默地胁迫。
______________________________________________________________________
非目标(v1)
- 无用户身份模型
- 无数据持久性
- 没有背景工作
- 无自动历史跟踪
- 无模糊AI练习映射(仅精确别名/显示;否则
unmapped:)
______________________________________________________________________
发展
对样本进行摄取(无状态)
python scripts/test_ingest.py
python scripts/test_ingest.py path/to/samples在示例导出的会话上运行指标
python scripts/test_metrics.py运行测试
pytest______________________________________________________________________
许可证
麻省理工学院
