Skip to content

feat(ingestion): Zep document_id grouping for zep-ingest 0.4.0 - #608

Open
jackaldenryan wants to merge 2 commits into
mainfrom
jack/aug-28
Open

feat(ingestion): Zep document_id grouping for zep-ingest 0.4.0#608
jackaldenryan wants to merge 2 commits into
mainfrom
jack/aug-28

Conversation

@jackaldenryan

Copy link
Copy Markdown
Contributor

Summary

  • Attach a stable document_id to text files, transcripts, and emails (including single-episode sources) so related chunks share one Zep document.
  • Slack is one episode per message: a document per Slack thread, plus a second document of each channel’s top-level messages (thread parents ingested twice; payload identical except document_id). JSON records stay standalone. The Slack grouping option is removed; Zep thread_id is not used.
  • Sequential graph.add sends document_id via a thin wrapper until the SDK types it; wait() polls the latest-created_at tail per document saga.
  • Unified live smoke suite (ingestion/scripts/smoke.py) runs after merge and after release without blocking either. Version is 0.4.0.

Test plan

  • Offline: uv run pytest tests/ -m "not integration and not smoke" (687 passed)
  • Prod: two-thread Slack ingest with pronoun cases (slack-pronoun-646362a9); Alice facts resolved for both Shes
  • After merge: dispatch Release Ingestion Package from main to publish zep-ingest-v0.4.0 (do not wait on post-merge CI first)
  • Confirm non-blocking Smoke Ingestion Package workflow is wired (needs ZEP_API_KEY in the integration environment)

Made with Cursor

…v0.4.0)

Group related episodes so extraction can resolve pronouns across chunks and
Slack threads, and add a non-blocking post-merge/release smoke suite.

Co-authored-by: Cursor <cursoragent@cursor.com>
assert [e.data for e in channel_eps] == [
next(e.data for e in eps if "Hello world" in e.data),
next(e.data for e in eps if "Should we deprioritize PROTOTYPE-202?" in e.data),
next(e.data for e in eps if "https://example.com" in e.data),

def test_markup_normalization(self):
markup = general(load())[2].data
markup = next(e.data for e in general(load()) if "https://example.com" in e.data)

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Criticalingestion/src/zep_ingest/result.py, record_sequential_episode() hunk: created_at values are compared lexicographically. Valid RFC3339 timestamps with differing offsets or fractional-second representations do not sort chronologically this way. wait() can therefore poll an earlier episode and return before the actual document tail is processed. Parse timestamps into normalized datetimes before selecting the maximum, and add offset/fractional-format tests.

  • Criticalingestion/src/zep_ingest/documents.py, document_id_for_path(): short absolute paths are sent verbatim as document_id. This exposes local directory/user/customer names to Zep and makes document identity change when the same file moves or runs on another machine, fragmenting re-ingestion. Always hash the path—or derive an explicitly scoped relative/content-based identifier—regardless of length.

  • Warning.github/workflows/smoke-ingestion.yml, checkout/install steps: the workflow_run path checks out current default-branch HEAD and uv sync installs the checkout, so the advertised post-release smoke test does not test the release commit or published artifact. Check out github.event.workflow_run.head_sha and install the released distribution/version before running the smoke suite.

Email Date headers mix timezone offsets; lexicographic created_at order
could poll the wrong saga. Post-release smoke now checks out the release SHA.

Co-authored-by: Cursor <cursoragent@cursor.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning — ingestion/src/zep_ingest/documents.py, document_id_for_path() hunk

document_id is derived from path.resolve(), making the same source file produce different IDs when checked out, mounted, or extracted under another directory. Re-ingesting it from CI, another machine, or a moved workspace creates a separate document instead of updating/grouping the existing one.

Use a location-independent identifier, such as a caller-supplied source-relative path or a stable content/source identifier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants