Orazaka
Pages of the documentation

Playbook: build a product on Orazaka

A worked example — what to deploy, in what order, and what each step delivers — written for decision-makers as much as engineers.

Developer playbook demonstrating how to build a product (CinePulse) on Orazaka.


1. CinePulse Product Case Study

CinePulse is a multi-modal entertainment discovery platform:

  • Text Recommendations: Moody/contextual query recommendations (e.g. "What to watch tonight?").
  • Audio Recognition: Identifies movie soundtracks using audio fingerprints.
  • Visual Recognition: Identifies movie screenshots, posters, or scenes.
ScreenPurposeOrazaka Pipeline
DashboardRecommendation feedUserContextResolver + RagInterceptor
RecognitionVisual/Audio media matchingVision + Audio pre-processor pipeline
WatchlistSaved watchlist trackingJPA persistence (Postgres)
StudioGenerates teaser video trailersVideoEngine (AnimateDiff-Lightning)
SettingsStreaming preferences and filter flagskrizaka-users-core preference profile

2. Architecture Mapping

Architecture · orazaka-business

Business persona prompts and PromptOps content resolver — pure library module

Repository
orazaka-ai-engine
Role
application
Owner
orazaka

Uses

  • orazaka-core
  • orazaka-studio-api
  • orazaka-studio-client

Used by

  • orazaka-conversation-service
  • orazaka-job-service

Every CinePulse turn — text over SSE, an audio clip or an image over REST — goes through the same interceptor pipeline before a model is called. The pipeline below is read from the code and the database order:

Interceptor pipeline — text version

Core chain: always, in the order of the code

  1. 1SafetyInterceptor · validation
    Stops a turn that carries crisis content and answers it with the pack's fixed, reviewed text.
  2. 2ScopeGuardInterceptor · governance
    Refuses a turn that strays into the domain its pack declared out of bounds (ADR-051).
  3. 3UserContextResolver · context
    Extracts user profile attributes and RBAC security configurations from the Spring Security context and enriches the `PromptContext`'s user metadata.
  4. 4SystemContextInjector · context
    Single atomic service responsible for both resolving system/environment state and injecting it into the timeline.
  5. 5RagInterceptor · enrichment
    RAG (Retrieval-Augmented Generation) interceptor — enriches the prompt with relevant knowledge base context retrieved via `KnowledgeService`.

Configured chain: in the database order

  1. 1UserContextResolver · context · core
    Extracts user profile attributes and RBAC security configurations from the Spring Security context and enriches the `PromptContext`'s user metadata.
  2. 2SystemContextInjector · context · core
    Single atomic service responsible for both resolving system/environment state and injecting it into the timeline.
  3. 3RagInterceptor · enrichment · core
    RAG (Retrieval-Augmented Generation) interceptor — enriches the prompt with relevant knowledge base context retrieved via `KnowledgeService`.
  4. 4EntitlementInterceptor · governance · dynamic
    Gates the synchronous chat path on what the actor may do and can afford (ADR-033 §6.2).
  5. 5McpInterceptor · enrichment · dynamic
    MCP (Model Context Protocol) interceptor — enriches the prompt with external context resolved via the `McpOrchestrator`.
  6. 6BrandContextInterceptor · enrichment · dynamic
    Injects an installed Studio's brand kit into the prompt (ADR-034 §9.1).
  7. 7MemoryInterceptor · enrichment · dynamic
    Conversation memory interceptor — injects historical messages before inference and persists new messages after completion.
  8. 8RefinerInterceptor · reformulation · dynamic
    Resolves fuzzy user questions against compiled context matrices and reformulates them into clear, explicit instructions using an LLM call.
  9. 9RouterInterceptor · reformulation · dynamic
    Analyzes user intent and selects the optimal AI provider using an LLM classification call with temperature 0.0 for determinism.
  10. 9ToolInterceptor · tooling · dynamic
    Tool execution interceptor — analyzes prompt content to selectively attach relevant `ToolCallback` definitions to the chat options.
  11. 10MediaInterceptor · · dynamic(not built yet)
  12. 11UserContextInterceptor · context · dynamic
    ContextInterceptor that dynamically injects onboarding profile details (ai_behavior, primary_industry) as structural system prompt constraints right before executing model inference or streaming.

3. Step-by-Step Implementation

Step 1: Database Model (orazaka-persistence/app)

java
@Entity
@Table(name = "cinepulse_movies")
public class MovieEntity {
    @Id private Long tmdbId;
    private String title;
    private String originalTitle;
    private String overview;
    private String genres; // JSON list
    private String posterPath;
    private Double imdbRating;
    private LocalDate releaseDate;
    
    @Convert(converter = JsonMapConverter.class)
    private Map<String, Boolean> streamingAvailability;
    
    @Column(columnDefinition = "vector(1536)")
    private float[] embedding; // PGVector embedding
}
  • Migration (V12__cinepulse_movies.sql):

    sql
    CREATE TABLE cinepulse_movies (
        tmdb_id BIGINT PRIMARY KEY,
        title VARCHAR(500) NOT NULL,
        overview TEXT,
        genres JSONB NOT NULL DEFAULT '[]',
        poster_path VARCHAR(255),
        imdb_rating DECIMAL(3,1),
        streaming_availability JSONB NOT NULL DEFAULT '{}',
        embedding vector(1536)
    );
    CREATE INDEX idx_movies_genres ON cinepulse_movies USING GIN (genres);
    CREATE INDEX idx_movies_embedding ON cinepulse_movies USING ivfflat (embedding vector_cosine_ops);

Step 2: Register Tools (orazaka-tools)

java
@Component
public class TmdbLookupTool {
    @Tool(description = "Search TMDb movies metadata")
    public MovieResult searchMovie(@ToolParam("Title query") String query) { ... }

    @Tool(description = "Check streaming availability across platforms")
    public StreamingResult checkAvailability(@ToolParam("TMDb ID") Long tmdbId, @ToolParam("Country code") String country) { ... }
}

Step 3: Embed Movies Catalog (RAG)

java
@Service
public class MovieEmbeddingService {
    private final EmbeddingModel embeddingModel;
    private final MovieRepository movieRepository;

    @Transactional
    public void embedMovieCatalog(List<MovieEntity> movies) {
        movies.forEach(movie -> {
            String text = String.format("%s. %s.", movie.getTitle(), movie.getOverview());
            movie.setEmbedding(embeddingModel.embed(text));
        });
        movieRepository.saveAll(movies);
    }
}

Step 4: Controller Mapping (orazaka-conversation-service)

java
@RestController
@RequestMapping("/api/v1/cinepulse")
public class CinePulseController {
    private final AiClient aiClient;

    @PostMapping("/recommend")
    public Flux<ChatResponse> recommend(@RequestBody RecommendRequest req, @RequestHeader("Authorization") String token) {
        return aiClient.stream(AiRequest.builder()
            .prompt(req.query())
            .context(Context.fromToken(token))
            .tools("tmdb-lookup")
            .build());
    }
}

4. Operational Playbook

Build Sequence

bash
# 1. Build identity logic
mvn clean install -pl krizaka/krizaka-users/krizaka-users-core

# 2. Compile gateway API with dependencies
mvn clean compile -pl orazaka-apps/services/orazaka-conversation-service -am

# 3. Build CLI executable
npm run build --prefix orazaka-apps/ui/orazaka-cli

# 4. Install UI workspace dependencies
npm install --prefix orazaka-apps/ui

Start Services

bash
# Docker databases, Redis & RabbitMQ
docker compose -f infra/docker-compose.yml up -d

# Spin up Ollama
ollama serve &
ollama pull llama3.2:latest

CLI Multi-Modal Usage

bash
# Authenticate
npx orazaka login [email protected] password123

# Prompt Recommendations
npx orazaka chat "Romantic movie recommendation for tonight"

# Identify Soundtrack Audio
npx orazaka chat --audio "var/soundtrack.mp3" "What movie is this song from?"

# Analyze Movie Poster Image
npx orazaka chat --image "var/poster.png" "Who is the director of this movie?"

# Generate Teaser Video
npx orazaka video "An animated camera flythrough of a futuristic neon city" --duration 4 --output "scratch/teaser.mp4"

5. Environment Reference

KeyDefaultPurpose
SPRING_DATASOURCE_URLjdbc:postgresql://localhost:5432/orazaka_dbMain PostgreSQL database
REDIS_URLredis://localhost:6379Cache rate limits & tokens
SPRING_RABBITMQ_HOSTlocalhostRabbitMQ event broker
VIDEO_WORKER_PORT8188Local Python SVD XT worker probe port
TMDB_API_KEY(required)TMDb metadata client
ACOUSTID_API_KEY(required)Audio fingerprinting service
NEXTAUTH_SECRET(required)BFF cookie encryption

Edit this page on GitHub