@remnic/bench 9.6.17 → 9.6.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -0
- package/dist/demo/mcp-memory-server.d.ts +1 -0
- package/dist/demo/mcp-memory-server.js +129 -0
- package/dist/index.d.ts +414 -6
- package/dist/index.js +2983 -268
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -16,6 +16,71 @@ pnpm add @remnic/bench
|
|
|
16
16
|
|
|
17
17
|
The CLI loads `@remnic/bench` via a computed-specifier dynamic import. If it's not installed, `remnic bench *` prints a clear install hint; the rest of the CLI keeps working.
|
|
18
18
|
|
|
19
|
+
## OpenAI Build Week: five-minute MemCorrect path
|
|
20
|
+
|
|
21
|
+
MemCorrect scores correction uptake and stale-memory harm through the same
|
|
22
|
+
`remnic bench` surface. This keyless smoke path uses the packaged stdio MCP
|
|
23
|
+
server, so it tests the actual MCP adapter rather than the in-memory baseline:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
remnic bench run --quick memcorrect-v1 --adapter mcp --mcp-demo
|
|
27
|
+
remnic bench runs list
|
|
28
|
+
remnic bench export <run-id> --format html --output ./memcorrect-report.html
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The run itself is deterministic and offline. It needs no dataset or API key.
|
|
32
|
+
The generated HTML is self-contained and includes the correction ledger,
|
|
33
|
+
per-dimension evidence, task drill-down, and reproducibility provenance. Treat
|
|
34
|
+
the packaged demo as a transport and product smoke test, not a publishable
|
|
35
|
+
backend-quality result.
|
|
36
|
+
|
|
37
|
+
From a source checkout, build the optional companion before invoking the CLI:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pnpm install --frozen-lockfile
|
|
41
|
+
pnpm --filter @remnic/bench build
|
|
42
|
+
pnpm exec tsx packages/remnic-cli/src/index.ts bench run \
|
|
43
|
+
--quick memcorrect-v1 --adapter mcp --mcp-demo
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
An external MCP server can replace `--mcp-demo` with exactly one of:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# stdio
|
|
50
|
+
remnic bench run --quick memcorrect-v1 --adapter mcp \
|
|
51
|
+
--mcp-command memory-server --mcp-args '["--stdio"]' \
|
|
52
|
+
--mcp-tool-map '{"store":"memory_store","recall":"memory_recall","correct":"memory_correct","reset":"memory_reset"}'
|
|
53
|
+
|
|
54
|
+
# Streamable HTTP; set REMNIC_BENCH_MCP_BEARER_TOKEN if authentication is required
|
|
55
|
+
remnic bench run --quick memcorrect-v1 --adapter mcp \
|
|
56
|
+
--mcp-url https://memory.example/mcp \
|
|
57
|
+
--mcp-tool-map '{"store":"memory_store","recall":"memory_recall","correct":"memory_correct","reset":"memory_reset"}'
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Tool names alone may not be enough for a non-canonical server. The mapping can
|
|
61
|
+
also describe argument semantics; see `remnic bench --help` for the current CLI
|
|
62
|
+
surface and use preflight failures as conformance errors rather than empty
|
|
63
|
+
recall scores.
|
|
64
|
+
|
|
65
|
+
GPT-5.6 judging is explicit and uses the OpenAI Responses API:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
export OPENAI_API_KEY=...
|
|
69
|
+
remnic bench run --quick memcorrect-v1 --adapter mcp --mcp-demo \
|
|
70
|
+
--judge-provider openai --judge-model gpt-5.6
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Codex built and adversarially reviewed the Build Week adapter, Responses
|
|
74
|
+
provider, and report card. The underlying Remnic engine and original benchmark
|
|
75
|
+
harness are prior work. The evidence ledger, credential-dependent frontier-run
|
|
76
|
+
placeholder, and release status live in the root [`HACKATHON.md`](../../HACKATHON.md).
|
|
77
|
+
|
|
78
|
+
The claimed judge path requires Node.js 22.12+. It is verified from source and
|
|
79
|
+
from packed tarballs installed into a clean global prefix on Linux; macOS is
|
|
80
|
+
supported with the same Node CLI but still needs a release-install receipt.
|
|
81
|
+
Windows judges should use WSL2; native Windows is not currently claimed as
|
|
82
|
+
Build Week-verified.
|
|
83
|
+
|
|
19
84
|
## What it does
|
|
20
85
|
|
|
21
86
|
- **Benchmark runners** for a growing set of memory-oriented evals: `longmemeval`, `locomo`, `memory-arena`, `amemgym`, `ama-bench`, plus a lightweight smoke fixture.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/demo/mcp-memory-server.ts
|
|
4
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
|
|
8
|
+
// src/demo/mcp-memory-correction.ts
|
|
9
|
+
function parseSyntheticCorrection(content) {
|
|
10
|
+
const trimmed = content.trim();
|
|
11
|
+
const patterns = [
|
|
12
|
+
{
|
|
13
|
+
expression: /^Correction: replace (.+) with (.+)\.$/s,
|
|
14
|
+
oldValueIndex: 1,
|
|
15
|
+
newValueIndex: 2
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
expression: /^Correction: my .+? record saying (.+?) is wrong\. It is now (.+)\.$/s,
|
|
19
|
+
oldValueIndex: 1,
|
|
20
|
+
newValueIndex: 2
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
expression: /^Oh by the way, we switched .+? from (.+?) to (.+) last month\.$/s,
|
|
24
|
+
oldValueIndex: 1,
|
|
25
|
+
newValueIndex: 2
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
expression: /^For this project, .+? is (.+?) now, not (.+)\.$/s,
|
|
29
|
+
oldValueIndex: 2,
|
|
30
|
+
newValueIndex: 1
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
expression: /^Update: .+? is (.+?) going forward instead of (.+)\.$/s,
|
|
34
|
+
oldValueIndex: 2,
|
|
35
|
+
newValueIndex: 1
|
|
36
|
+
}
|
|
37
|
+
];
|
|
38
|
+
for (const pattern of patterns) {
|
|
39
|
+
const match = pattern.expression.exec(trimmed);
|
|
40
|
+
const oldValue = match?.[pattern.oldValueIndex];
|
|
41
|
+
const newValue = match?.[pattern.newValueIndex];
|
|
42
|
+
if (oldValue !== void 0 && newValue !== void 0) return { oldValue, newValue };
|
|
43
|
+
}
|
|
44
|
+
return void 0;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// src/demo/mcp-memory-server.ts
|
|
48
|
+
var memories = /* @__PURE__ */ new Map();
|
|
49
|
+
var server = new McpServer({
|
|
50
|
+
name: "remnic-bench-demo-memory",
|
|
51
|
+
version: "1.0.0"
|
|
52
|
+
});
|
|
53
|
+
server.registerTool(
|
|
54
|
+
"store_memory",
|
|
55
|
+
{
|
|
56
|
+
description: "Store one synthetic benchmark memory in an isolated session.",
|
|
57
|
+
inputSchema: {
|
|
58
|
+
namespace: z.string(),
|
|
59
|
+
sessionId: z.string(),
|
|
60
|
+
content: z.string(),
|
|
61
|
+
role: z.string().optional(),
|
|
62
|
+
timestamp: z.string().optional()
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
async ({ sessionId, content }) => {
|
|
66
|
+
memories.set(sessionId, [...memories.get(sessionId) ?? [], content]);
|
|
67
|
+
return { content: [{ type: "text", text: JSON.stringify({ stored: true }) }] };
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
server.registerTool(
|
|
71
|
+
"search_memory",
|
|
72
|
+
{
|
|
73
|
+
description: "Recall memories from one isolated benchmark session.",
|
|
74
|
+
inputSchema: {
|
|
75
|
+
namespace: z.string(),
|
|
76
|
+
sessionId: z.string(),
|
|
77
|
+
query: z.string(),
|
|
78
|
+
limit: z.number().int().positive().optional()
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
async ({ sessionId, limit }) => ({
|
|
82
|
+
content: [
|
|
83
|
+
{
|
|
84
|
+
type: "text",
|
|
85
|
+
text: JSON.stringify({ memories: (memories.get(sessionId) ?? []).slice(0, limit) })
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
})
|
|
89
|
+
);
|
|
90
|
+
server.registerTool(
|
|
91
|
+
"correct_memory",
|
|
92
|
+
{
|
|
93
|
+
description: "Apply a synthetic natural-language correction to one session.",
|
|
94
|
+
inputSchema: {
|
|
95
|
+
namespace: z.string(),
|
|
96
|
+
sessionId: z.string(),
|
|
97
|
+
content: z.string(),
|
|
98
|
+
timestamp: z.string().optional()
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
async ({ sessionId, content }) => {
|
|
102
|
+
const replacement = parseSyntheticCorrection(content);
|
|
103
|
+
const current = memories.get(sessionId) ?? [];
|
|
104
|
+
if (replacement) {
|
|
105
|
+
memories.set(
|
|
106
|
+
sessionId,
|
|
107
|
+
current.map((item) => item.replaceAll(replacement.oldValue, replacement.newValue))
|
|
108
|
+
);
|
|
109
|
+
} else {
|
|
110
|
+
memories.set(sessionId, [...current, content]);
|
|
111
|
+
}
|
|
112
|
+
return { content: [{ type: "text", text: JSON.stringify({ applied: true }) }] };
|
|
113
|
+
}
|
|
114
|
+
);
|
|
115
|
+
server.registerTool(
|
|
116
|
+
"delete_memory",
|
|
117
|
+
{
|
|
118
|
+
description: "Delete only the requested isolated benchmark session.",
|
|
119
|
+
inputSchema: {
|
|
120
|
+
namespace: z.string(),
|
|
121
|
+
sessionId: z.string()
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
async ({ sessionId }) => {
|
|
125
|
+
memories.delete(sessionId);
|
|
126
|
+
return { content: [{ type: "text", text: JSON.stringify({ deleted: true }) }] };
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
await server.connect(new StdioServerTransport());
|