要求(对应 REQUIRE.md):
--module <name> 将根目录已存在的模块目录 <name>/ 注入到 pikapython-linux/pikapython/ 参与一次性构建,结束后清理。test_example.py:python run_pika.py --module test_module_example test_example.py 可直接运行通过。核心准则:简单、单一、可预测。
根目录已有示例模块目录:
test_module_example/
├─ test_module_example.pyi
└─ test_module_example_Test.c
示例脚本:test_example.py
运行:
python run_pika.py --module test_module_example test_example.py
期望输出包含:
[EXAMPLE] add(7, 35)= 42
[EXAMPLE][SELFTEST] test_module_example OK
运行完成后,注入到 pikapython-linux/pikapython/ 的 .pyi 与 pikascript-lib/test_module_example/ 会被自动清理,只保留根目录原始示例。
.pyi 文件:定义模块的类与方法签名(声明式),预编译器扫描后生成 C 头文件 + 绑定代码。pikapython-linux/pikapython/pikascript-lib/<module>/,函数名模式:<module>_<Class>_<method>。wine rust-msc-latest-win10.exe 把 .py + .pyi 打包到自动生成的 pikascript-api 中。run_pika.py 会临时替换 main.py 内容,编译并运行后恢复。
(本指南仅使用“根目录已有模块 + --module 注入 + 运行后清理”这一条路径。)放置位置(根目录):
<module>/
<module>.pyi
<module>_*.c (可一个或多个 C 源文件)
构建时通过:
python run_pika.py --module <module> your_script.py
脚本会:
<module>.pyi 到 pikapython-linux/pikapython/<module>_*.c 到 pikapython-linux/pikapython/pikascript-lib/<module>/main.py 开头未导入则插入 import <module>(保证预编译扫描)main.py,删除复制进去的 .pyi 和临时 C 目录建议放置在 file_create/ 下:
<module>_test.py 或 <module>_demo.py[EXAMPLE] ...[EXAMPLE][SELFTEST] <module> OK[PERF] python_total=... mean=...us / cmod_total=... / speedup(...)= ...xassert 直接失败可暴露栈信息为直观展示 C 模块与纯 Python 版本性能差异,测试脚本中应:
def py_add(a,b): return a+b)。ITER = 10000,循环分别调用 Python 与 C 版本累计时间。time.time()(兼容环境)计时;不依赖 statistics、perf_counter 或复杂表达式。输出格式示例:
[PERF] python_total=0.002345s mean=23.45us
[PERF] cmod_total=0.000980s mean=9.80us
[PERF] speedup(py_mean/c_mean)= 2.39x
最终仍需打印 [EXAMPLE][SELFTEST] <module> OK。
注意:保持算法极简,避免引入在精简运行时不可用的库。
根目录:
test_module_example/
test_module_example.pyi
test_module_example_Test.c
test_example.py
示例脚本 test_example.py(含性能对比精简实现):
import time
import test_module_example
def py_add(a, b):
return a + b
obj = test_module_example.Test()
print('[EXAMPLE] add(7, 35)=', obj.add(7, 35))
print('[EXAMPLE] greet:"', obj.greet('demo'), '"', sep='')
assert obj.add(1, 2) == 3
assert obj.greet('x').startswith('Hello,')
ITER = 10000
py_total = 0.0
c_total = 0.0
for _ in range(ITER):
t0 = time.time(); py_add(123,456); py_total += (time.time()-t0)
t1 = time.time(); obj.add(123,456); c_total += (time.time()-t1)
if ITER > 0:
py_mean = py_total / ITER
c_mean = c_total / ITER
else:
py_mean = c_mean = 0.0
ratio = py_mean / c_mean if c_mean > 0 else 0.0
print('[PERF] python_total=' + ('%.6f' % py_total) + 's mean=' + ('%.2f' % (py_mean*1e6)) + 'us')
print('[PERF] cmod_total=' + ('%.6f' % c_total) + 's mean=' + ('%.2f' % (c_mean*1e6)) + 'us')
print('[PERF] speedup(py_mean/c_mean)= ' + ('%.2f' % ratio) + 'x')
print('[EXAMPLE][SELFTEST] test_module_example OK')
运行:
python run_pika.py --module test_module_example test_example.py
| 现象 | 排查 | 解决 |
|---|---|---|
| 运行输出缺少新模块方法 | 未导入模块 | 确认脚本或插入的 import 存在 |
| 链接时报 undefined reference | C 函数命名不匹配 | 确认 <module>_<Class>_<method> 命名并重新构建 |
| 重复残留导致拒绝注入 | 上次异常未清理 | 重新运行会先删除遗留;若失败手工清理 build/ 内残留再尝试 |
| 字符串返回乱码 | 未使用缓存返回 | 用 obj_cacheStr(self, buf) 返回局部缓冲内容 |
| 修改 .pyi 不生效 | 仍在用旧构建 | 删除 build/ 或确保触发重新 cmake(注入时自动触发) |
.pyi 增加 float / bytes / 指针类型以测试类型映射。file_create/ 下 *_test.py 并逐一运行收集 [SELFTEST] 行。run_pika.py 中解析运行日志并生成 JSON 汇总。.pyi + C。如需新增更复杂示例或自动化测试框架,请在 Issue/需求中提出。
本指南采用唯一“根目录已有模块 + --module 注入”模式。无其它路径,无生成,无回退。
自 Client.py 引入自定义重试后,所有 LLM 调用遵循以下规则:
max_retries=0),完全由自定义逻辑控制。1, 2, 5, 10, 30, 60, 120,共 7 次等待 + 首次立即调用 = 最多 8 次尝试。可通过环境变量覆盖:
export LLM_RETRY_DELAYS="0.5,1,2,4,8"
失败判定:捕获所有异常(包括 4xx 如余额不足 402、临时网络问题、限流等)。不中途过滤,以支持在重试窗口内外部补款或限流恢复。
日志:
logs/session_<ts>/llm_retry.log(JSON,多条覆盖写入最终状态)。llm_final_error.log,并抛出异常终止图执行。成功后续:正常记录本次 usage 统计,照常写入 summary_stats.log。
若需彻底禁用重试(不建议),可将环境变量设置为 LLM_RETRY_DELAYS="" 或单元素 >=1,例如:export LLM_RETRY_DELAYS="1"。
此策略保证:
注意:一旦最终失败,外层交互模式会直接看到异常堆栈;非交互一次性模式会在统计输出前终止。