@@ -383,25 +383,122 @@ RedisVL includes an experimental VCR (Video Cassette Recorder) test system for r
383383- ** Deterministic tests** - Replay recorded responses for consistent results
384384- ** Cost reduction** - Avoid repeated API calls during test runs
385385- ** Speed improvement** - Local Redis playback is faster than API calls
386- - ** Offline testing** - Run tests without network access
386+ - ** Offline testing** - Run tests without network access or API keys
387+
388+ # ## Quick Start with JUnit 5
389+
390+ The simplest way to use VCR is with the declarative annotations:
387391
388392` ` ` java
389- import com.redis.vl.test.vcr.VCRTest;
390393import com.redis.vl.test.vcr.VCRMode;
394+ import com.redis.vl.test.vcr.VCRModel;
395+ import com.redis.vl.test.vcr.VCRTest;
391396
392397@VCRTest(mode = VCRMode.PLAYBACK_OR_RECORD)
393- public class MyLLMTest {
398+ class MyLLMTest {
399+
400+ // Models are automatically wrapped by VCR
401+ @VCRModel(modelName = " text-embedding-3-small" )
402+ private EmbeddingModel embeddingModel = createEmbeddingModel();
403+
404+ @VCRModel
405+ private ChatLanguageModel chatModel = createChatModel();
394406
395407 @Test
396- void testLLMResponse () {
408+ void testEmbedding () {
397409 // First run: Records API response to Redis
398410 // Subsequent runs: Replays from Redis cassette
399- String response = myLLMService.generate(" What is Redis? " );
411+ Response<Embedding> response = embeddingModel.embed(" What is Redis? " );
412+ assertNotNull(response.content());
413+ }
414+
415+ @Test
416+ void testChat() {
417+ String response = chatModel.generate(" Explain Redis in one sentence." );
400418 assertNotNull(response);
401419 }
402420}
403421` ` `
404422
423+ # ## VCR Modes
424+
425+ | Mode | Description | API Key Required |
426+ | ------| -------------| ------------------|
427+ | ` PLAYBACK` | Only use recorded cassettes. Fails if missing. | No |
428+ | ` PLAYBACK_OR_RECORD` | Use cassette if available, record if not. | Only for first run |
429+ | ` RECORD` | Always call real API and record response. | Yes |
430+ | ` OFF` | Bypass VCR, always call real API. | Yes |
431+
432+ # ## Environment Variable Override
433+
434+ Override the VCR mode at runtime without changing code:
435+
436+ ` ` ` bash
437+ # Record new cassettes
438+ VCR_MODE=RECORD OPENAI_API_KEY=your-key ./gradlew test
439+
440+ # Playback only (CI/CD, no API key needed)
441+ VCR_MODE=PLAYBACK ./gradlew test
442+ ` ` `
443+
444+ # ## LangChain4J Integration
445+
446+ ` ` ` java
447+ import com.redis.vl.test.vcr.VCREmbeddingModel;
448+ import com.redis.vl.test.vcr.VCRChatModel;
449+ import com.redis.vl.test.vcr.VCRMode;
450+
451+ // Wrap any LangChain4J EmbeddingModel
452+ VCREmbeddingModel vcrEmbedding = new VCREmbeddingModel(openAiEmbeddingModel);
453+ vcrEmbedding.setMode(VCRMode.PLAYBACK_OR_RECORD);
454+ Response< Embedding> response = vcrEmbedding.embed(" What is Redis?" );
455+
456+ // Wrap any LangChain4J ChatLanguageModel
457+ VCRChatModel vcrChat = new VCRChatModel(openAiChatModel);
458+ vcrChat.setMode(VCRMode.PLAYBACK_OR_RECORD);
459+ String response = vcrChat.generate(" What is Redis?" );
460+ ` ` `
461+
462+ # ## Spring AI Integration
463+
464+ ` ` ` java
465+ import com.redis.vl.test.vcr.VCRSpringAIEmbeddingModel;
466+ import com.redis.vl.test.vcr.VCRSpringAIChatModel;
467+ import com.redis.vl.test.vcr.VCRMode;
468+
469+ // Wrap any Spring AI EmbeddingModel
470+ VCRSpringAIEmbeddingModel vcrEmbedding = new VCRSpringAIEmbeddingModel(openAiEmbeddingModel);
471+ vcrEmbedding.setMode(VCRMode.PLAYBACK_OR_RECORD);
472+ EmbeddingResponse response = vcrEmbedding.embedForResponse(List.of(" What is Redis?" ));
473+
474+ // Wrap any Spring AI ChatModel
475+ VCRSpringAIChatModel vcrChat = new VCRSpringAIChatModel(openAiChatModel);
476+ vcrChat.setMode(VCRMode.PLAYBACK_OR_RECORD);
477+ String response = vcrChat.call(" What is Redis?" );
478+ ` ` `
479+
480+ # ## How It Works
481+
482+ 1. ** Container Management** : VCR starts a Redis Stack container with persistence
483+ 2. ** Model Wrapping** : ` @VCRModel` fields are wrapped with VCR proxies
484+ 3. ** Cassette Storage** : Responses stored as Redis JSON documents
485+ 4. ** Persistence** : Data saved to ` src/test/resources/vcr-data/` via Redis AOF/RDB
486+ 5. ** Playback** : Subsequent runs load cassettes from persistent storage
487+
488+ # ## Demo Projects
489+
490+ Complete working examples are available:
491+
492+ - ** [LangChain4J VCR Demo](demos/langchain4j-vcr/)** - LangChain4J embedding and chat models
493+ - ** [Spring AI VCR Demo](demos/spring-ai-vcr/)** - Spring AI embedding and chat models
494+
495+ Run the demos without an API key (uses pre-recorded cassettes):
496+
497+ ` ` ` bash
498+ ./gradlew :demos:langchain4j-vcr:test
499+ ./gradlew :demos:spring-ai-vcr:test
500+ ` ` `
501+
405502> Learn more about [VCR testing](https://redis.github.io/redis-vl-java/redisvl/current/vcr-testing.html).
406503
407504# # 🚀 Why RedisVL?
0 commit comments