session: add restricted Python DSL extraction protocol and make it the default - #4581
Open
chenjw wants to merge 6 commits into
Open
session: add restricted Python DSL extraction protocol and make it the default#4581chenjw wants to merge 6 commits into
chenjw wants to merge 6 commits into
Conversation
…e default
Introduce a restricted Python memory SDK output protocol as an alternative to
the JSON extraction protocol, and switch the default to python. Both protocols
share the same ResolvedOperations post-processing, schema rules, and patch-repair
path via a new ExtractionOutputProtocol abstraction.
- Add extraction_output_protocol/{base,json,python}.py; python compiles a
restricted AST into the same operations model as json.
- Default memory.extraction_output_format flips json -> python.
- Surface the offending source line on Python syntax errors and add targeted
triple-quote retry guidance for string-literal breaks.
- Preserve every distinct fact on canonical merges; remove hardcoded memory
type names from prompts so custom memory_types render dynamically.
- Downgrade benign batch-delete link-inheritance read failures to WARNING.
- Add memory_organization A/B benchmark and message_format pretty-printer.
Tests: extraction protocol, config loader, memory react suites pass.
Co-authored-by: TRAE CLI <traecli@bytedance.com>
…r-python-output Co-authored-by: TRAE CLI <traecli@bytedance.com> # Conflicts: # openviking/session/memory/extract_loop.py # openviking/session/memory/patch_merge_context_provider.py
- entities.yaml: remove the size-triggered split hint; when to split/compact is decided at read time by memory_maintenance_notice, so the static schema description only keeps the identity semantics and fact-preservation rule. - vlm/base.py: remove a duplicated @AbstractMethod on get_completion_async. Co-authored-by: TRAE CLI <traecli@bytedance.com>
volcengine already dropped its @tracer("volcengine.vlm.call") wrapper to avoid duplicate spans now that the request is logged via tracer.info(llm_input_messages=...). Remove the symmetric litellm/openai decorators so all three backends behave the same. Co-authored-by: TRAE CLI <traecli@bytedance.com>
ov.AsyncHTTPClient resolves to openviking_cli.client._http_compat.AsyncHTTPClient,
whose commit_session takes a flat telemetry= kwarg and has no options= parameter.
Passing options={...} (the SDK-client shape) raised TypeError during import.
Use telemetry=True to match the CLI client, consistent with the other locomo
import scripts.
Co-authored-by: TRAE CLI <traecli@bytedance.com>
…emetry The by-type extraction telemetry treated result.errors[].uri as a valid viking URI and fell back to MemoryUpdater.memory_type_from_uri(), but that field is an error *target* — it can be a sentinel like "unknown" or "events(page_id=100)". VikingURI() then raised 'URI must start with viking://', turning a single recorded extraction error into a crash of the whole long_term extraction step. Count failed errors by the known uri->type map only, defaulting to "unknown". Co-authored-by: TRAE CLI <traecli@bytedance.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Introduces a restricted Python memory SDK as an alternative output protocol for the memory extraction loop, and makes it the default (
memory.extraction_output_format: json -> python).The model emits restricted Python function calls (
sdk.create_events(...),obj.content.edit(...),obj.delete(replacement=...),obj.link(...)) that an AST compiler resolves into the exact sameResolvedOperationsstructure as the JSON protocol. Both protocols share oneExtractionOutputProtocolabstraction, so schema rules, patch-repair, URI resolution, and streaming merge are identical.Why
The JSON protocol struggles with transactional reorganization (create N files + delete source + inherit links), and long Markdown content frequently breaks JSON parsing. The Python DSL expresses references naturally via variables/object methods and parses via
ast.parse, giving precise error locations.Results — LoCoMo full eval (1540 Q, doubao-seed-2-0-code-preview)
Results — memory-organization A/B (controlled, 3 cases × 20 runs each, zh output)
Two independent metrics: 成功拆分合并 (was the required merge/migrate/split actually performed) and 信息完整 (every expected fact present exactly once in the final tree).
Case 1 —
entities/Projects/atlas.md+entities/projects/atlas.mdpoint to the same Atlas project with different facts; must merge into one canonical entity and remove/replacement the duplicate. Python's edge is both the multi-object create/delete/replacement organization and fact conservation during the merge.Case 2 — an oversized Profile mixes stable personal facts with several preference groups; preferences must be migrated into Preferences without touching stable facts.
Case 3 — an oversized Preference file mixes two dimensions and must split into ≥2 files with the oversized source deleted, preserving every fact exactly once.
The A/B harness lives in
benchmark/memory_organization/(run_ab.py, cases undercases/); it uses the same production prompt/Schema as the live pipeline.Key changes
extraction_output_protocol/{base,json,python}.py— protocol abstraction + implementations. Python compiles a restricted AST into the same operations model as JSON.python(memory_config.py,extract_loop.py,ov.conf.example).benchmark/memory_organization/A/B harness andopenviking/utils/message_format.pypretty-printer.How to reproduce
LoCoMo full eval
Select the protocol via
memory.extraction_output_format(python|json) inov.conf,start the server, then run the driver (imports conversations, waits for extraction, answers
QA, LLM-judges):
Each run writes an isolated dir
result/locomo/runs/<timestamp>/withlocomo_result.csv,import_success.csv,summary.txt, bot logs, and a snapshot of the produced memory files.Memory-organization A/B (JSON vs Python)
Same production prompt/Schema for both protocols; only the output protocol differs.
Tests
ruff check/ruff format --checkclean on changed files. Extraction protocol, config loader, memory react, patch-merge, and extract-loop match-text suites pass (173 targeted tests). Merged latestorigin/mainand resolved conflicts inextract_loop.py/patch_merge_context_provider.py. Six failures in the broader memory suite are pre-existing and unrelated to this PR (environment-dependent language detection that reads localov.confoutput_language_override, plusgraph_view/schema_modelstests untouched here).