Skip to content

docs: add Haystack cookbook - #51

Closed
atao2004 wants to merge 19 commits into
mainfrom
cookbook-haystack
Closed

atao2004 wants to merge 19 commits into
mainfrom
cookbook-haystack

Conversation

@atao2004

@atao2004 atao2004 commented Jul 21, 2026 •

Copy link
Copy Markdown

Closes #91

Summary

Migrates the Haystack + Valkey cookbook from the archive/main-pre-reorg branch, fully updated to conform with CONTRIBUTING.md guidelines (PR #40).

Depends on #45 (semantic-caching) — this branch is based on cookbook-semantic-caching and extends its shared cookbook-python.yml CI workflow. Merge #45 first.

Changes from the Original (archive/main-pre-reorg)

  • Replaced sentence-transformers embedder with OllamaDocumentEmbedder / OllamaTextEmbedder (vendor neutral, no API key)
  • Replaced OpenAIChatGenerator (paid) with OllamaChatGenerator as default (OpenAI in collapsible optional section)
  • Pinned Valkey to valkey/valkey-bundle:9.1.0 (not :latest)
  • Added security callout, audience line, config reference, teardown sections
  • Added sample/ directory with runnable main.py and CI-friendly test_haystack.py
  • Tests use Haystack's built-in MockDocumentEmbedder / MockTextEmbedder — no Ollama needed in CI
  • Extended cookbook-python.yml matrix with framework-integrations/haystack
  • Requires Python 3.10+ (all three packages require it)

Cookbook Structure

cookbooks/framework-integrations/haystack/
├── README.md                    # Index with 2-cookbook table
├── 01-getting-started.md        # Beginner · ~15 min
├── 02-rag-pipeline.md           # Intermediate · ~20 min
└── sample/
    ├── README.md                # How to run + expected output
    ├── docker-compose.yml       # Valkey Bundle 9.1.0 with healthcheck
    ├── requirements.txt         # haystack-ai>=3.0.0, valkey-haystack==0.2.2, ollama-haystack>=6.0.0
    ├── main.py                  # Full RAG demo (requires Ollama)
    ├── test_haystack.py         # CI tests with mock embedders (no Ollama)
    └── .gitignore

Technical Details

Component Choice Rationale
Embedding model nomic-embed-text (768-dim, 274MB) Matches ValkeyDocumentStore default
Chat model llama3.2:1b (1.3GB) Smallest instruction-tuned model for RAG
Embedder components OllamaDocumentEmbedder + OllamaTextEmbedder Free, local, no API key
Generator OllamaChatGenerator Free, local, vendor neutral
Valkey image valkey/valkey-bundle:9.1.0 Required for Search + JSON modules
CI test strategy MockDocumentEmbedder / MockTextEmbedder Deterministic, no model downloads in CI
Client library valkey-glide (via valkey-haystack) Pre-built manylinux wheels for cp311/x86_64

Validation

  • Markdown lint: 0 issues across all 4 .md files
  • Python syntax: Both .py files compile cleanly
  • QA review: 1 critical finding caught and fixed (MockDocumentEmbedder param name), all others clean

Vendor Neutrality

  • No paid API dependencies in the default path
  • Ollama runs entirely locally (nomic-embed-text for embeddings, llama3.2:1b for chat)
  • OpenAI shown as optional alternative in a collapsible <details> section
  • valkey-haystack is the official Haystack integration (deepset-maintained)

Known Risks

  • haystack-ai>=3.0.0 requirement (MockDocumentEmbedder only exists in 3.0+). If valkey-haystack==0.2.2 has runtime incompatibilities with 3.0, fallback: use pre-computed embeddings directly on Document objects instead of mock embedders.
  • ValkeyDocumentStore uses JSON storage (not Hash) — requires both search and json Valkey modules (hence bundle image).

Relationship to Other PRs

atao2004 added 7 commits July 14, 2026 18:20
- 3 progressive cookbooks: getting-started, multi-turn caching, production patterns
- sample/ directory with runnable demo (Ollama + Valkey) and CI-friendly tests
- Python CI workflow testing against valkey-bundle:9.1.0
- Uses Ollama (free, local) as default embedding provider; OpenAI as optional alternative
- Tests use deterministic vectors (no Ollama dependency in CI)
- Requires valkey-search >= v1.2.0 (valkey-bundle 9.x); 8.x search module lacks TEXT field support
- Updated .markdownlint.jsonc: allow details/summary HTML, disable MD060

Signed-off-by: Anna Tao <annatao2004@gmail.com>
…formance

Fixes all findings from code review:

Critical:
- Align main.py and test_cache.py with docs: use TEXT (not TAG) for prompt/response fields
- Add sanitize_tag_value() to prevent query injection in user_id interpolation

Warnings:
- Add PREFIX filter to 02-multiturn-caching.md FT.CREATE
- Compute embedding once in ask_with_cache, pass to lookup and cache (eliminates double call)
- Use pipeline for HSET + EXPIRE (single round-trip)
- Add socket_timeout=5.0 to all Valkey client constructors
- Make test_different_vector_exceeds_threshold self-contained (no ordering dependency)
- Add scan_iter cleanup for test_cache:* keys in fixture teardown
- Replace time.sleep with wait_for_indexing polling loop
- Fix invalidate_by_topic to use TEXT query syntax @prompt:(keyword)
- Add pip caching to CI workflow
- Pin ruff==0.11.13 with --output-format=github for PR annotations

Signed-off-by: Anna Tao <annatao2004@gmail.com>
- Fix evaluate_threshold: pass both args to semantic_cache_lookup(query, query_vec)
- Add sanitize_ft_query() to invalidate_by_topic preventing query DSL injection
- Add Authentication and TLS rows to Production Checklist
- Extract parse_ft_search_fields() helper in test_cache.py (DRY refactor)

Signed-off-by: Anna Tao <annatao2004@gmail.com>
Changes to cookbook-python.yml itself now trigger the workflow,
ensuring CI validates the workflow is correct when it's modified.

Signed-off-by: Anna Tao <annatao2004@gmail.com>
- Remove outdated 'must run first' message from self-contained test
- Add timeout-minutes: 10 to integration-test job
- Add TestEdgeCases::test_knn_on_empty_index

Signed-off-by: Anna Tao <annatao2004@gmail.com>
- 2 cookbooks: Getting Started (Beginner) + RAG Pipeline (Intermediate)
- Replaces sentence-transformers + OpenAI with Ollama (vendor neutral)
- OllamaDocumentEmbedder/OllamaTextEmbedder for embeddings (nomic-embed-text, 768-dim)
- OllamaChatGenerator for RAG generation (llama3.2:1b, local)
- OpenAI shown as optional alternative in collapsible section
- sample/ with runnable main.py demo and CI-friendly test_haystack.py
- Tests use MockDocumentEmbedder/MockTextEmbedder (no Ollama needed in CI)
- Extends cookbook-python.yml matrix with framework-integrations/haystack
- Requires haystack-ai>=3.0.0 (MockDocumentEmbedder introduced in 3.0)
- ValkeyDocumentStore uses GLIDE + JSON storage (requires valkey-bundle)
- All markdown passes markdownlint, Python syntax verified

Signed-off-by: Anna Tao <annatao2004@gmail.com>
…deps

- Downgrade to haystack-ai==2.28.0 (proven working, no 3.0 risk)
- Pin valkey-glide==2.5.0 + valkey-glide-sync==2.5.0 explicitly
- Replace MockDocumentEmbedder with fixed 4-dim vectors (no version dep)
- Add store.close() in try/finally blocks (proper GLIDE lifecycle)
- Add VALKEY_HOST/VALKEY_PORT/VALKEY_REQUEST_TIMEOUT_MS env overrides
- Add metadata filtering (category tag) to sample and cookbook
- Add deepset affiliation disclosure to README
- Test against both valkey-bundle 8.1.4 and 9.1.1 in CI
- docker-compose binds to 127.0.0.1 (not 0.0.0.0)

Signed-off-by: Anna Tao <annatao2004@gmail.com>

@MatthiasHowellYopp MatthiasHowellYopp left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

COMMENT — Large, well-structured PR with two cookbooks (Haystack + Semantic Caching). Security posture is strong: FT.SEARCH uses parameterized values, TAG filters sanitized, TEXT search escaped. 9 substantive findings below (all warnings, none blocking).

Comment thread cookbooks/use-cases/semantic-caching/02-multiturn-caching.md Outdated
Comment thread cookbooks/use-cases/semantic-caching/sample/docker-compose.yml Outdated
Comment thread cookbooks/framework-integrations/haystack/sample/requirements.txt Outdated
Comment thread cookbooks/use-cases/python/semantic-caching/sample/main.py Outdated
Comment thread cookbooks/use-cases/python/semantic-caching/sample/test_cache.py Outdated
Comment thread cookbooks/use-cases/python/semantic-caching/sample/README.md Outdated
Comment thread cookbooks/use-cases/semantic-caching/sample/test_cache.py Outdated
Comment thread .github/workflows/cookbook-python.yml Outdated
- Sanitize user_id in store_conversation_cache (key namespace consistency)
- Bind semantic-caching docker-compose to 127.0.0.1 (not 0.0.0.0)
- Pin ollama-haystack==6.5.0 (was unpinned >=6.0.0)
- Close Valkey client at end of main() and in test fixture teardown
- Fix test ordering dependency: clean keys + expected_docs=1
- Add Valkey Bundle 9.0+ to semantic-caching prerequisites
- Add request_timeout to haystack config reference table
- Add workflow path to dorny/paths-filter patterns

Signed-off-by: Anna Tao <annatao2004@gmail.com>
@MatthiasHowellYopp

Copy link
Copy Markdown
Collaborator

Re-review: All findings addressed ✅

Commit 53fe53ff resolves all 9 findings from the initial review:

  1. ✅ Key injection — store_conversation_cache now sanitizes user_id before using it in the cache key
  2. ✅ Port binding — both docker-compose.yml files bind to 127.0.0.1
  3. ✅ Unpinned dep — ollama-haystack pinned to ==6.5.0
  4. ✅ Client never closed — client.close() called at end of main()
  5. ✅ Test fixture client — client.close() in fixture teardown
  6. ✅ Missing version requirement — README now states Valkey Bundle 9.0+
  7. ✅ Config reference — request_timeout added to table
  8. ✅ Cross-test ordering — self-contained tests
  9. ✅ Workflow self-trigger — .github/workflows/cookbook-python.yml in paths filter

Additional positives: env var overrides in main.py, try/finally cleanup pattern, failure-path test (cleanup_closes_store_when_deletion_fails), CI tests against both 8.1.4 and 9.1.1.

Verdict: Approve — will formally approve once undrafted.

@jbrinkman jbrinkman added the Cookbook Cookbooks are tutorials with runnable code that highlights how to use Valkey in specific scenarios label Jul 27, 2026
@jbrinkman
jbrinkman marked this pull request as ready for review August 13, 2026 11:20

@jbrinkman jbrinkman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Cookbook Review — Haystack + Semantic Caching

[AI Review] Reviewed against CONTRIBUTING.md standards:

  • ❌ Directory structure & naming
  • ✅ Issue context & requirements verification
  • ✅ Upstream Valkey support verification
  • ✅ Markdown structure & mandatory elements
  • ✅ Acceptance criteria & vendor neutrality
  • ✅ Sample code quality
  • ✅ CI validation

Summary

  • Total findings: 3
  • Blocking: 2
  • Suggestions: 1

Key Issues

  • ❌ Missing python/ language directory for framework-integrations/haystack/
  • ❌ Missing python/ language directory for use-cases/semantic-caching/
  • ⚠️ Inline docker run commands bind to all interfaces instead of localhost

Please address the blocking issues above before merging.

Comment thread cookbooks/framework-integrations/python/haystack/README.md
Comment thread cookbooks/use-cases/python/semantic-caching/README.md Outdated
Comment thread cookbooks/framework-integrations/haystack/01-getting-started.md Outdated
atao2004 and others added 5 commits August 13, 2026 23:30
- Move Haystack and Semantic Caching under Python directories
- Bind local Docker examples to loopback

Signed-off-by: Anna Tao <annatao2004@gmail.com>
PR #43's dynamic discovery handles Python cookbooks automatically
via `find cookbooks -path "*/sample/requirements.txt"`. No per-cookbook
workflow file needed.

Signed-off-by: MatthiasHowellYopp <matthias.howell@improving.com>
- Rename generic 'client' → 'valkeyClient' in semantic-caching sample
- Rename generic 'store' → 'valkeyStore' in haystack sample + tests
- Align Haystack docker-compose to 9.1.0 (matches tutorial + other sample)
- Separate security callout from Podman note in semantic-caching
- Add lifecycle comment on close() in semantic-caching sample

Signed-off-by: MatthiasHowellYopp <matthias.howell@improving.com>
Keep the focus on Valkey + Haystack. Docker-only prerequisites; drop the
podman-substitution note (Security callout remains as its own blockquote).

Signed-off-by: MatthiasHowellYopp <matthias.howell@improving.com>
- haystack: optional cloud generation now uses OpenRouter via
  OpenAIChatGenerator(api_base_url=...) instead of OpenAI/gpt-4o (vendor-neutral)
- semantic-caching: relabel the hosted-embedder alternative and note OpenRouter
  has no embeddings endpoint (default stays Ollama nomic-embed-text)
- fix NameError in test_haystack.py: cleanup test referenced valkeyStore but
  declared 'store' (regression from the earlier rename; caught by running tests)

Verified: haystack 4/4 and semantic-caching 5/5 sample tests pass;
OpenAIChatGenerator api_base_url support confirmed against haystack-ai 2.28.0.

Signed-off-by: MatthiasHowellYopp <matthias.howell@improving.com>

@jbrinkman jbrinkman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The use-cases/python/semantic-caching cookbook should be in it's own PR and not included in the Haystack cookbook. Please split this into a separate PR and move to the Bit-quill repo as a draft.

Comment thread cookbooks/framework-integrations/python/haystack/sample/.gitignore
Comment thread cookbooks/framework-integrations/python/haystack/sample/docker-compose.yml Outdated
Comment thread cookbooks/framework-integrations/python/haystack/sample/main.py Outdated
Comment thread cookbooks/framework-integrations/python/haystack/sample/README.md Outdated
Comment thread cookbooks/framework-integrations/python/haystack/01-getting-started.md Outdated
atao2004 and others added 2 commits August 17, 2026 15:40
…arted.md

Co-authored-by: Joe Brinkman <joe.brinkman@improving.com>
Signed-off-by: Anna Tao <annatao2004@gmail.com>
Signed-off-by: Anna Tao <annatao2004@gmail.com>

@MatthiasHowellYopp MatthiasHowellYopp left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

One small naming nit on the sample — non-blocking. Thanks for the embedder rework and the cookbook isolation; both look great.

Comment thread cookbooks/framework-integrations/python/haystack/sample/main.py Outdated
- Rename store locals and helper parameters to valkey_store

Signed-off-by: Anna Tao <annatao2004@gmail.com>

@MatthiasHowellYopp MatthiasHowellYopp left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-reviewed at f766fbf against the current cookbook guidelines. This is in strong shape — real SentenceTransformers embedders (no more deterministic stub), all deps pinned, valkey_store naming, try/finally + close(), structured filter dicts (no injection), 127.0.0.1 binding, 9.1.2, and a vendor-neutral OpenRouter alternative in a <details>. I've resolved my earlier threads that this commit addressed (ollama-haystack pin, request_timeout in the config table, the store→valkey_store rename) and resolved the semantic-caching threads since that cookbook was split into its own draft.

Two minor, non-blocking polish items below (same single-source-the-version / standalone-runnable pattern we're applying across the cookbooks), plus one scope observation:

Scope note (judgment call, no change requested): Under our "scope each recipe to Valkey's role" guideline, generation is normally handed off with a pointer since Valkey's role ends at retrieval. 02 keeps the full ChatPromptBuilder/OllamaChatGenerator generation — and I think that's defensible here in a way it wasn't for langchain4j: there the generation was dead commented-out code; here it's live, local, and the composable Pipeline wiring (retriever.documents → prompt_builder.documents → generator) is the Haystack integration story. Flagging only so the choice is deliberate — your call whether to keep the full generator or trim to the retriever hand-off + a pointer to Haystack's generator docs.

Comment thread cookbooks/framework-integrations/python/haystack/01-getting-started.md Outdated
Comment thread cookbooks/framework-integrations/python/haystack/02-rag-pipeline.md
atao2004 and others added 2 commits August 18, 2026 09:13
- Centralize Valkey startup and teardown through Docker Compose
- Make the RAG pipeline page independently runnable

Signed-off-by: Anna Tao <annatao2004@gmail.com>
Resolve .markdownlint.jsonc: keep main's updated base (MD013/MD040/MD041)
and re-apply this cookbook's additions (MD033 details/summary + MD060 disable).

Signed-off-by: MatthiasHowellYopp <matthias.howell@improving.com>

@Jonathan-Improving Jonathan-Improving left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

APPROVE — Well-structured Haystack + Valkey cookbook.

Reviewed: All 10 files (4 markdown docs, sample code, tests, docker-compose, requirements, .gitignore, markdownlint config).

Highlights:

  • Correct haystack-ai 2.x import paths and component API usage
  • Proper GLIDE lifecycle management via valkey-haystack (try/finally + close())
  • Security callout present; docker binds to 127.0.0.1 only
  • Internal markdown cross-links verified (01↔02, README→both)
  • Tests use real SentenceTransformers embeddings (384-dim) — deterministic without external services
  • Clean separation: sample uses sentence-transformers (no Ollama needed), cookbook docs teach Ollama workflow
  • All dependencies pinned to exact versions
  • Filter dict format ({"field": ..., "operator": ..., "value": ...}) correct for Haystack 2.x

No blocking findings. Previous reviewer concerns (directory structure, localhost binding, store naming) all addressed in this revision.

Align this Python sample's .gitignore with the other Python cookbook samples
(haystack/lmcache/mem0) so they share one canonical ignore list: broaden
*.pyc -> *.py[cod], add .ruff_cache/ (samples run ruff), and cover
venv/.env/egg-info/dist/build. Addresses the cross-sample consistency note.

Signed-off-by: MatthiasHowellYopp <matthias.howell@improving.com>
@jbrinkman

Copy link
Copy Markdown
Collaborator

Closing this PR as the cookbook work is being tracked internally. The branch and all commits have been preserved. Thank you for the contribution!

@jbrinkman jbrinkman closed this Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Cookbook Cookbooks are tutorials with runnable code that highlights how to use Valkey in specific scenarios

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Proposal] Add Haystack + Valkey cookbook (Python document store)

4 participants