Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed architecture.png
Binary file not shown.
687 changes: 315 additions & 372 deletions benchmark.py

Large diffs are not rendered by default.

Binary file removed demo.mp4
Binary file not shown.
33 changes: 28 additions & 5 deletions scripts/xmem.js
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,33 @@ function ensurePrerequisites(skipPython = false) {
}
}

function pythonHasPip(pythonPath) {
return run(pythonPath, ["-m", "pip", "--version"], { capture: true, allowFailure: true }).status === 0;
}

function ensureVirtualenv() {
const venvPython = venvPythonPath();
if (!fs.existsSync(venvPython)) {
log("Creating XMem virtualenv");
run(systemPythonCommand(), ["-m", "venv", path.join(root, ".venv")]);
}

if (!pythonHasPip(venvPython)) {
log("Repairing XMem virtualenv pip");
const result = run(venvPython, ["-m", "ensurepip", "--upgrade"], {
allowFailure: true,
});
if (result.status !== 0 || !pythonHasPip(venvPython)) {
fail(
"XMem virtualenv was created, but pip is unavailable. Reinstall Python with venv/pip support, delete .venv, and rerun npm run setup.",
2,
);
}
}

return venvPython;
}

function setupLooksComplete(reposDir) {
return (
fs.existsSync(path.join(root, "pyproject.toml")) &&
Expand Down Expand Up @@ -586,11 +613,7 @@ function runSetup(args) {
}

if (!options.skipPythonInstall) {
const venvPython = venvPythonPath();
if (!fs.existsSync(venvPython)) {
log("Creating XMem virtualenv");
run(systemPythonCommand(), ["-m", "venv", path.join(root, ".venv")]);
}
const venvPython = ensureVirtualenv();
log("Installing XMem local dependencies");
run(venvPython, ["-m", "pip", "install", "--upgrade", "pip"]);
run(venvPython, ["-m", "pip", "install", "-e", `${root}[local,dev]`]);
Expand Down
6 changes: 6 additions & 0 deletions src/prompts/examples/temporal.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@
"2:35 pm on 16 March, 2023",
"DATE: 03-09\nEVENT_NAME: Started Gym\nYEAR: 2023\nDESC: Started going to the gym\nTIME: \nDATE_EXPRESSION: last week",
),
# Relative date — today
(
"I started a new job at Vercel as a frontend developer today!",
"4:00 pm on 20 May, 2026",
"DATE: 05-20\nEVENT_NAME: Started New Job\nYEAR: 2026\nDESC: Started a new job at Vercel as a frontend developer\nTIME: \nDATE_EXPRESSION: today",
),
# Relative date — next month
(
"I'm getting ready for a dance comp near me next month.",
Expand Down
1 change: 1 addition & 0 deletions src/prompts/temporal.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
You will be given a CONTEXT_DATE which is the date/time when the conversation occurred.
Use this to resolve relative expressions:

- "today" → use CONTEXT_DATE
- "yesterday" → subtract 1 day from CONTEXT_DATE
- "tomorrow" → add 1 day to CONTEXT_DATE
- "next Friday" → find the next Friday after CONTEXT_DATE
Expand Down
36 changes: 24 additions & 12 deletions xmem-go/cmd/benchmark/main.go → xmem-go/cmd/smoke_test/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ func (t *TimedModel) GenerateWithMessages(ctx context.Context, msgs []models.Mes
return resp, err
}

func (t *TimedModel) GenerateVision(ctx context.Context, systemPrompt string, userText string, imageURL string) (models.Response, error) {
start := time.Now()
resp, err := t.inner.GenerateVision(ctx, systemPrompt, userText, imageURL)
atomic.AddInt64(&t.llmTime, int64(time.Since(start)))
atomic.AddInt64(&t.calls, 1)
return resp, err
}

func (t *TimedModel) SelectTools(ctx context.Context, query string, catalog []map[string]string) (models.Response, error) {
start := time.Now()
resp, err := t.inner.SelectTools(ctx, query, catalog)
Expand Down Expand Up @@ -85,7 +93,11 @@ func main() {
os.Exit(1)
}

realModel := models.NewRegistry(settings)
realModel, err := models.NewRegistry(settings)
if err != nil {
fmt.Fprintf(os.Stderr, "model registry error: %v\n", err)
os.Exit(1)
}
fmt.Printf("Model: %s\n\n", realModel.Name())

ctx := context.Background()
Expand All @@ -109,7 +121,7 @@ func main() {
total := time.Since(start)
t := timing{"Classifier Agent", total, tm.LLMDuration(), total - tm.LLMDuration(), tm.CallCount(), false}
timings = append(timings, t)
fmt.Printf(" %-30s total=%-10s llm=%-10s overhead=%-10s calls=%d results=%d\n", t.name, t.total.Round(time.Millisecond), t.llm.Round(time.Millisecond), t.overhead.Round(time.Microsecond), t.calls, len(result))
fmt.Printf(" %-30s results=%d\n", t.name, len(result))
}

// Profiler
Expand All @@ -121,7 +133,7 @@ func main() {
total := time.Since(start)
t := timing{"Profiler Agent", total, tm.LLMDuration(), total - tm.LLMDuration(), tm.CallCount(), false}
timings = append(timings, t)
fmt.Printf(" %-30s total=%-10s llm=%-10s overhead=%-10s calls=%d facts=%d\n", t.name, t.total.Round(time.Millisecond), t.llm.Round(time.Millisecond), t.overhead.Round(time.Microsecond), t.calls, len(result))
fmt.Printf(" %-30s facts=%d\n", t.name, len(result))
}

// Temporal
Expand All @@ -133,7 +145,7 @@ func main() {
total := time.Since(start)
t := timing{"Temporal Agent", total, tm.LLMDuration(), total - tm.LLMDuration(), tm.CallCount(), false}
timings = append(timings, t)
fmt.Printf(" %-30s total=%-10s llm=%-10s overhead=%-10s calls=%d events=%d\n", t.name, t.total.Round(time.Millisecond), t.llm.Round(time.Millisecond), t.overhead.Round(time.Microsecond), t.calls, len(result))
fmt.Printf(" %-30s events=%d\n", t.name, len(result))
}

// Summarizer
Expand All @@ -145,7 +157,7 @@ func main() {
total := time.Since(start)
t := timing{"Summarizer Agent", total, tm.LLMDuration(), total - tm.LLMDuration(), tm.CallCount(), false}
timings = append(timings, t)
fmt.Printf(" %-30s total=%-10s llm=%-10s overhead=%-10s calls=%d bullets=%d\n", t.name, t.total.Round(time.Millisecond), t.llm.Round(time.Millisecond), t.overhead.Round(time.Microsecond), t.calls, len(result))
fmt.Printf(" %-30s bullets=%d\n", t.name, len(result))
}

// Judge (deterministic profile path — no LLM)
Expand All @@ -158,11 +170,11 @@ func main() {
{Topic: "work", SubTopic: "title", Memo: "Senior Software Engineer"},
}
start := time.Now()
result := agent.JudgeProfile(ctx, facts)
result := agent.JudgeProfile(ctx, facts, "bench-user")
total := time.Since(start)
t := timing{"Judge (deterministic)", total, tm.LLMDuration(), total - tm.LLMDuration(), tm.CallCount(), false}
timings = append(timings, t)
fmt.Printf(" %-30s total=%-10s llm=%-10s overhead=%-10s calls=%d ops=%d\n", t.name, t.total.Round(time.Millisecond), t.llm.Round(time.Millisecond), t.overhead.Round(time.Microsecond), t.calls, len(result.Operations))
fmt.Printf(" %-30s ops=%d\n", t.name, len(result.Operations))
}

// Judge (LLM path — summary domain)
Expand All @@ -179,7 +191,7 @@ func main() {
total := time.Since(start)
t := timing{"Judge (LLM)", total, tm.LLMDuration(), total - tm.LLMDuration(), tm.CallCount(), false}
timings = append(timings, t)
fmt.Printf(" %-30s total=%-10s llm=%-10s overhead=%-10s calls=%d ops=%d\n", t.name, t.total.Round(time.Millisecond), t.llm.Round(time.Millisecond), t.overhead.Round(time.Microsecond), t.calls, len(result.Operations))
fmt.Printf(" %-30s ops=%d\n", t.name, len(result.Operations))
}

fmt.Println(strings.Repeat("─", 70))
Expand All @@ -205,7 +217,7 @@ func main() {
Summarizer: agents.SummarizerAgent{Model: tm},
Image: agents.ImageAgent{Model: tm},
Snippet: agents.SnippetAgent{Model: tm},
Judge: agents.JudgeAgent{Model: tm, VectorStore: memStore, TopK: 3},
Judge: agents.JudgeAgent{Model: tm, VectorStore: memStore, TemporalStore: tempStore, TopK: 3},
}

req := contracts.IngestRequest{
Expand All @@ -222,7 +234,7 @@ func main() {
} else {
t := timing{"Full Ingest Pipeline", total, tm.LLMDuration(), total - tm.LLMDuration(), tm.CallCount(), true}
timings = append(timings, t)
fmt.Printf(" %-30s total=%-10s llm_sum=%-10s calls=%d (parallel — LLM sum > wall clock)\n", t.name, t.total.Round(time.Millisecond), t.llm.Round(time.Millisecond), t.calls)
fmt.Printf(" %-30s calls=%d (parallel)\n", t.name, t.calls)
fmt.Printf(" classifications=%d", len(resp.Classification))
if resp.Profile != nil {
fmt.Printf(" profile_ops=%d", len(resp.Profile.Operations))
Expand Down Expand Up @@ -262,7 +274,7 @@ func main() {
} else {
t := timing{"Full Retrieval Pipeline", total, tm.LLMDuration(), total - tm.LLMDuration(), tm.CallCount(), false}
timings = append(timings, t)
fmt.Printf(" %-30s total=%-10s llm=%-10s overhead=%-10s calls=%d\n", t.name, t.total.Round(time.Millisecond), t.llm.Round(time.Millisecond), t.overhead.Round(time.Microsecond), t.calls)
fmt.Printf(" %-30s calls=%d\n", t.name, t.calls)
fmt.Printf(" answer=%q sources=%d confidence=%.2f\n", truncate(resp.Answer, 80), len(resp.Sources), resp.Confidence)
}
}
Expand Down Expand Up @@ -294,7 +306,7 @@ func main() {
total := time.Since(start)
t := timing{"Concurrent Pipeline Sim", total, tm.LLMDuration(), total - tm.LLMDuration(), tm.CallCount(), true}
timings = append(timings, t)
fmt.Printf(" %-30s total=%-10s llm_sum=%-10s calls=%d (parallel — LLM sum > wall clock)\n", t.name, t.total.Round(time.Millisecond), t.llm.Round(time.Millisecond), t.calls)
fmt.Printf(" %-30s calls=%d (parallel)\n", t.name, t.calls)
}

// --- Summary Table ---
Expand Down
Loading
Loading