Skip to content

Conversation

@Hi-kue
Copy link
Contributor

@Hi-kue Hi-kue commented Jun 9, 2025

NOTE: I would more than likely consider this a draft PR, still working on a couple fixes and making sure its ready for use.

Summary by CodeRabbit

  • New Features

    • Introduced AI image generation endpoints with support for both Google Gemini and Together AI providers.
    • Added streaming summarization endpoint for real-time summary delivery.
    • Added modular prompt templates for both summarization and image generation tasks.
    • Implemented backend service automation via a new task runner file.
    • Provided Docker Compose configuration for local PostgreSQL database setup.
  • Improvements

    • Refined AI model configurations and prompt structures for better clarity and output quality.
    • Enhanced environment configuration with additional AI provider variables and clearer sample values.
    • Updated summarization logic to use the latest Google GenAI client and improved error handling.
    • Expanded type definitions and validation schemas for AI-related requests and responses.
  • Bug Fixes

    • Corrected minor documentation typos in configuration files.
  • Chores

    • Improved logging consistency across backend scripts and environment loading.
    • Refactored code structure for easier service and strategy management.

@Hi-kue Hi-kue requested a review from Mindful-Developer as a code owner June 9, 2025 07:52
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 9, 2025

Walkthrough

This update introduces a comprehensive AI image generation feature alongside significant refactoring and enhancements to the summarization module. It adds new controllers, services, strategies, types, prompts, and validation schemas for image generation, with support for both Gemini and Together AI providers. Summarization now supports streaming, uses an updated client, and improved prompt structures. Supporting scripts, configuration files, and environment variables are also updated or added.

Changes

File(s) / Group Change Summary
backend/.env.sample Updated with explicit defaults, added Firebase/AI config vars, clarified comments, and reorganized OAuth/Stripe sections.
backend/docker-compose.yml Added Docker Compose config for a Postgres service with persistent volume.
backend/justfile Added Justfile for backend task automation (setup, build, clean, test, run).
backend/package.json Swapped "@google/generative-ai" for "@google/genai", added "together-ai" dependency.
backend/scripts/config.sh New script for color-coded, timestamped logging functions in shell scripts.
backend/scripts/deploy_test_pg_db.sh Changed shebang to use env for portability.
backend/scripts/test_data.sql Reformatted UPDATE statement for readability; logic unchanged.
backend/src/modules/ai/config/models.ts Split and refactored model configs for summarization and image generation; added detailed safety settings.
backend/src/modules/ai/config/prompts.ts Rewrote summarization prompts; added detailed, modular prompts for image generation.
backend/src/modules/ai/controllers/generation.controller.ts New controller for image generation endpoints with placeholder methods.
backend/src/modules/ai/controllers/summarization.controller.ts Added streaming summarization endpoint handler.
backend/src/modules/ai/routes/generation.routes.ts New Express router for image generation endpoints with validation.
backend/src/modules/ai/routes/summarization.routes.ts Renamed router, added streaming summarization route.
backend/src/modules/ai/services/generation.service.ts New service using strategy pattern for image generation with provider validation.
backend/src/modules/ai/services/imagen/google.service.ts New Gemini image generation service implementing strategy interface.
backend/src/modules/ai/services/imagen/together.service.ts New Together AI image generation service implementing strategy interface.
backend/src/modules/ai/services/imagen/index.ts Added index file to re-export image generation services.
backend/src/modules/ai/services/index.ts Added index file to re-export summarization and generation services.
backend/src/modules/ai/services/summarization.service.ts Refactored to use new GenAI client, centralized env validation, added streaming support, improved error handling.
backend/src/modules/ai/strategy/generation.strategy.ts New interface for image generation strategies.
backend/src/modules/ai/types/generation.types.ts New types and Zod schemas for image generation requests/responses.
backend/src/modules/ai/types/index.ts Re-exported new image generation types.
backend/src/modules/ai/types/models.types.ts Added/expanded enums and interfaces for AI/image generation models and configs.
backend/src/modules/ai/types/summarization.types.ts Improved error messages; added streaming response/chunk types.
backend/src/modules/ai/utils/ai.utils.ts New utility for AI provider environment variable validation.
backend/src/shared/config/environment.ts Added new AI-related env vars, improved logging, clarified error messages.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API_Router
    participant ImageGenController
    participant ImageGenService
    participant Strategy (Gemini/Together)
    participant AIProviderAPI

    Client->>API_Router: POST /generate/single or /generate/multiple
    API_Router->>ImageGenController: validate + route request
    ImageGenController->>ImageGenService: generate(request)
    ImageGenService->>Strategy: generate(request)
    Strategy->>AIProviderAPI: Call AI image generation API
    AIProviderAPI-->>Strategy: Return image(s)
    Strategy-->>ImageGenService: Return result
    ImageGenService-->>ImageGenController: Return result
    ImageGenController-->>API_Router: Return image(s)
    API_Router-->>Client: Respond with image(s)
Loading
sequenceDiagram
    participant Client
    participant API_Router
    participant SummarizationController
    participant SummarizationService
    participant GoogleGenAI

    Client->>API_Router: POST /summarize/stream
    API_Router->>SummarizationController: validate + route request
    SummarizationController->>SummarizationService: summarizeStream(request)
    SummarizationService->>GoogleGenAI: generateContentStream(request)
    GoogleGenAI-->>SummarizationService: Stream summary chunks
    SummarizationService-->>SummarizationController: Return stream & metadata
    SummarizationController-->>API_Router: Respond with streaming summary
    API_Router-->>Client: Return summary stream
Loading

Possibly related PRs

  • Turing-Sandbox/Summarizz#124: Introduced the foundational AI module and environment variables, upon which this PR builds with expanded features for AI summarization and image generation.

Poem

🐇✨
In the warren of code, new features bloom,
AI crafts images, and summaries resume.
Gemini and Together, side by side,
Prompts and configs, meticulously applied.
Streaming words and pictures now appear—
A rabbit's delight, the future is here!
🖼️📄

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 22

🧹 Nitpick comments (21)
backend/docker-compose.yml (2)

3-3: Pin Postgres image version

Using latest can introduce breaking changes unexpectedly. Recommend specifying a major (or minor) version, e.g. postgres:15-alpine.


6-9: Extract sensitive credentials to environment file

Hard-coding DB credentials in docker-compose.yml poses maintainability and security risks. Consider moving POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB into an external .env and referencing them via env_file or ${VAR} interpolation.

backend/scripts/deploy_test_pg_db.sh (1)

1-1: Add strict mode and cleanup trap

While using #!/usr/bin/env bash is more portable, the script should fail fast and ensure the temporary PGPASS_FILE is removed on errors. For example:

 #!/usr/bin/env bash
+set -euo pipefail
+trap 'rm -f "$PGPASS_FILE"' EXIT
backend/scripts/test_data.sql (1)

247-261: Optimize metric aggregation with a single CTE

Updating each row with two separate subqueries can be expensive. Consider computing like/share counts in a CTE and performing one join:

WITH counts AS (
  SELECT
    content_id,
    COUNT(*) FILTER (WHERE interaction_type = 'like')  AS likes,
    COUNT(*) FILTER (WHERE interaction_type = 'share') AS shares
  FROM user_content_interactions
  GROUP BY content_id
)
UPDATE content c
SET
  likes  = counts.likes,
  shares = counts.shares
FROM counts
WHERE c.content_id = counts.content_id;
backend/src/modules/ai/controllers/summarization.controller.ts (1)

36-40: Reconsider logging timing for streaming responses.

Logging stream.metadata.processingTime for a streaming response may not provide accurate timing information, as streams are typically processed incrementally. Consider either logging when the stream completes or clarifying what this timing represents.

-      logger.info('Successfully generated summary stream', {
+      logger.info('Successfully initiated summary stream', {
         textLength: requestData.text.length,
-        processingTime: stream.metadata.processingTime,
+        initiationTime: stream.metadata.processingTime,
         model: stream.metadata.model,
       });
backend/src/modules/ai/strategy/generation.strategy.ts (1)

9-13: Consider improving type safety with generic constraints.

The interface correctly implements the strategy pattern, but the union return type makes it difficult for consumers to know which response type to expect. Consider using generics or method overloads for better type safety.

 export interface ImageGenerationStrategy {
-    generate(
-        request: LowerTierImageGenerationRequest | HigherTierImageGenerationRequest
-    ): Promise<LowerTierImageGenerationResponse | HigherTierImageGenerationResponse>;
+    generate(request: LowerTierImageGenerationRequest): Promise<LowerTierImageGenerationResponse>;
+    generate(request: HigherTierImageGenerationRequest): Promise<HigherTierImageGenerationResponse>;
+    generate(
+        request: LowerTierImageGenerationRequest | HigherTierImageGenerationRequest
+    ): Promise<LowerTierImageGenerationResponse | HigherTierImageGenerationResponse>;
 }
backend/src/modules/ai/controllers/generation.controller.ts (1)

3-5: Remove unused imports.

Several imports are currently unused due to the placeholder implementation.

Since the methods are not yet implemented, consider removing unused imports until they're actually needed:

-import { createSuccessResponse } from '../../../shared/utils/response';
-import { logger } from '../../../shared/utils/logger';
-import { ImageGenerationResponse } from '../types';
backend/.env.sample (1)

30-30: Verify the "Algoria" typo in the comment.

The comment was changed from "ALGOLIA" to "Algoria," which appears to be a typo. The service name should remain "Algolia."

-# Algoria Search API
+# Algolia Search API
backend/scripts/config.sh (1)

11-12: Consider removing unused color variables or export them for external use.

Static analysis identified COLOR_CYAN and COLOR_WHITE as unused. Either remove them if not needed or export them if they're intended for use in scripts that source this file.

-    COLOR_CYAN=$(tput setaf 6)
-    COLOR_WHITE=$(tput setaf 7)

Or export them if intended for external use:

-    COLOR_CYAN=$(tput setaf 6)
-    COLOR_WHITE=$(tput setaf 7)
+    export COLOR_CYAN=$(tput setaf 6)
+    export COLOR_WHITE=$(tput setaf 7)

Also applies to: 21-22

backend/src/modules/ai/services/imagen/google.service.ts (2)

5-5: Remove unused import.

The Together import from 'together-ai' is not used in this file and should be removed.

-import Together from 'together-ai';

38-44: Remove unnecessary null check after constructor.

The check if (!genAI) is unnecessary because the GoogleGenAI constructor will either return a valid instance or throw an error. It won't return null or undefined.

-        if (!genAI) {
-            throw new AppError(
-                500,
-                'Failed to initialize Google GenAI client. Please check your environment variables.',
-                APP_ERROR_SOURCE
-            );
-        }
-
         return genAI;
backend/src/modules/ai/services/imagen/together.service.ts (3)

3-3: Remove unused import.

The GoogleGenAI import from '@google/genai' is not used in this file and should be removed.

-import { GoogleGenAI } from '@google/genai';

39-45: Remove unnecessary null check after constructor.

Similar to the Google service, the check if (!togetherAI) is unnecessary because the constructor will either return a valid instance or throw an error.

-        if (!togetherAI) {
-        throw new AppError(
-            500,
-            'Failed to initialize Together AI client. Please check your environment variables.',
-            APP_ERROR_SOURCE
-        );
-        }
-
         return togetherAI;

58-58: Fix typo in TODO comment.

-             * TODO: Implement Together AI Image Generation Logc
+             * TODO: Implement Together AI Image Generation Logic
backend/justfile (1)

59-61: Remove redundant argument check.

The check for empty $arg is unnecessary since the recipe already has a default value of "default" defined on line 54.

-    if [ -z "$arg" ]; then \
-        arg="default" \
-    fi
backend/src/modules/ai/services/summarization.service.ts (1)

34-40: Remove unnecessary null check.

The check for !genAI is redundant. If the GoogleGenAI constructor fails, it will throw an error rather than returning null or undefined.

-    if (!genAI) {
-      throw new AppError(
-        500, 
-        'Failed to initialize Google GenAI client. Please check your environment variables.', 
-        APP_ERROR_SOURCE
-      );
-    }
-
backend/src/modules/ai/types/generation.types.ts (3)

47-57: Remove redundant TODO comment and ensure consistency.

The HigherTierImageGenerationRequest interface is actually properly implemented and matches the Zod schema structure, so the TODO comment is misleading.

Apply this diff to remove the misleading TODO:

-// TODO: Refactor implementation HigherTierImageGenerationRequest
 export interface HigherTierImageGenerationRequest {
   prompt: string;
   options?: {
     model?: AIGenerationModel;
     width?: number;
     height?: number;
     steps?: number;
     disable_safety_checker?: boolean;
   };
 }

75-77: Remove the commented export statement.

The commented export with the extremely long interface name appears to be leftover code or a joke comment that should be removed.

Apply this diff to clean up the file:

-/**
- * export interface ExpensivelyHighForAbsolutelyNoReasonOtherThanToShowOffWeAreAbleToMakeHighQualityImagesFromTheirAPIImageGenerationRequest {}
- */

5-18: Consider consolidating the Zod schemas to reduce duplication.

Both LowerTierImageGenerationRequestSchema and HigherTierImageGenerationRequestSchema are nearly identical except for the prompt max length. This creates maintenance overhead.

Consider creating a factory function to generate schemas with different prompt limits:

+const createImageGenerationRequestSchema = (maxPromptLength: number) => z.object({
+  body: z.object({
+    prompt: z.string().min(1, 'Prompt must not be empty.').max(maxPromptLength, 'Provided prompt is too long.'),
+    options: z.object({
+      model: z.nativeEnum(AIGenerationModel).optional(),
+      width: z.number().positive().optional(),
+      height: z.number().positive().optional(),
+      steps: z.number().int().positive().optional(),
+      disable_safety_checker: z.boolean().optional(),
+    }).optional(),
+  }),
+  query: z.object({}).optional(),
+  params: z.object({}).optional(),
+});
+
-export const LowerTierImageGenerationRequestSchema = z.object({
-  body: z.object({
-    prompt: z.string().min(1, 'Prompt must not be empty.').max(1000, 'Provided prompt is too long.'),
-    options: z.object({
-      model: z.nativeEnum(AIGenerationModel).optional(),
-      width: z.number().positive().optional(),
-      height: z.number().positive().optional(),
-      steps: z.number().int().positive().optional(),
-      disable_safety_checker: z.boolean().optional(),
-    }).optional(),
-  }),
-  query: z.object({}).optional(),
-  params: z.object({}).optional(),
-});

-export const HigherTierImageGenerationRequestSchema = z.object({
-  body: z.object({
-    prompt: z.string().min(1, 'Prompt must not be empty.').max(10000, 'Provided prompt is too long.'),
-    options: z.object({
-      model: z.nativeEnum(AIGenerationModel).optional(),
-      width: z.number().positive().optional(),
-      height: z.number().positive().optional(),
-      steps: z.number().int().positive().optional(),
-      disable_safety_checker: z.boolean().optional(),
-    }).optional(),
-  }),
-  query: z.object({}).optional(),
-  params: z.object({}).optional(),
-});

+export const LowerTierImageGenerationRequestSchema = createImageGenerationRequestSchema(1000);
+export const HigherTierImageGenerationRequestSchema = createImageGenerationRequestSchema(10000);

Also applies to: 20-33

backend/src/modules/ai/types/models.types.ts (2)

9-14: Consider standardizing model naming conventions.

The AIGenerationModel enum has inconsistent naming patterns. Some models use camelCase (TogetherFlux1Dev) while others mix naming styles.

Consider standardizing the naming convention:

 export enum AIGenerationModel {
-  Gemini20FlashImageGenPreview = 'gemini-2.0-flash-preview-image-generation',
+  Gemini20FlashImageGeneration = 'gemini-2.0-flash-preview-image-generation',
   TogetherFlux1Dev = 'black-forest-labs/FLUX.1-dev',
   TogetherFlux1Schnell = 'black-forest-labs/FLUX.1-schnell',
   TogetherFlux1SchnellFree = 'black-forest-labs/FLUX.1-schnell-Free',
 }

Also, verify that the TogetherFlux1SchnellFree value ending with -Free is correct as it appears inconsistent with the others ending with lowercase.


34-44: Consider breaking down the large ModelConfig interface.

The ModelConfig interface has grown significantly with many optional fields. This could lead to maintainability issues and unclear usage patterns.

Consider breaking this into more focused interfaces:

+export interface BaseModelConfig {
+  temperature?: number;
+  topP?: number;
+  topK?: number;
+  maxOutputTokens?: number;
+  stopSequences?: string[];
+}
+
+export interface SafetyModelConfig {
+  safetySettings?: SafetySetting[];
+}
+
+export interface AdvancedModelConfig {
+  systemInstruction?: string;
+  thinkingConfig?: ThinkingConfig;
+  httpOptions?: HttpOptions;
+}
+
-export interface ModelConfig {
-  safetySettings?: SafetySetting[];
-  systemInstruction?: string;
-  temperature?: number;
-  topP?: number;
-  topK?: number;
-  maxOutputTokens?: number;
-  stopSequences?: string[];
-  thinkingConfig?: ThinkingConfig;
-  httpOptions?: HttpOptions;
-}
+export interface ModelConfig extends BaseModelConfig, SafetyModelConfig, AdvancedModelConfig {}

This approach provides better composition and clearer separation of concerns.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e634609 and 9b44ec4.

📒 Files selected for processing (26)
  • backend/.env.sample (2 hunks)
  • backend/docker-compose.yml (1 hunks)
  • backend/justfile (1 hunks)
  • backend/package.json (2 hunks)
  • backend/scripts/config.sh (1 hunks)
  • backend/scripts/deploy_test_pg_db.sh (1 hunks)
  • backend/scripts/test_data.sql (1 hunks)
  • backend/src/modules/ai/config/models.ts (1 hunks)
  • backend/src/modules/ai/config/prompts.ts (1 hunks)
  • backend/src/modules/ai/controllers/generation.controller.ts (1 hunks)
  • backend/src/modules/ai/controllers/summarization.controller.ts (1 hunks)
  • backend/src/modules/ai/routes/generation.routes.ts (1 hunks)
  • backend/src/modules/ai/routes/summarization.routes.ts (1 hunks)
  • backend/src/modules/ai/services/generation.service.ts (1 hunks)
  • backend/src/modules/ai/services/imagen/google.service.ts (1 hunks)
  • backend/src/modules/ai/services/imagen/index.ts (1 hunks)
  • backend/src/modules/ai/services/imagen/together.service.ts (1 hunks)
  • backend/src/modules/ai/services/index.ts (1 hunks)
  • backend/src/modules/ai/services/summarization.service.ts (1 hunks)
  • backend/src/modules/ai/strategy/generation.strategy.ts (1 hunks)
  • backend/src/modules/ai/types/generation.types.ts (1 hunks)
  • backend/src/modules/ai/types/index.ts (1 hunks)
  • backend/src/modules/ai/types/models.types.ts (1 hunks)
  • backend/src/modules/ai/types/summarization.types.ts (2 hunks)
  • backend/src/modules/ai/utils/ai.utils.ts (1 hunks)
  • backend/src/shared/config/environment.ts (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (8)
backend/src/modules/ai/strategy/generation.strategy.ts (1)
backend/src/modules/ai/types/generation.types.ts (4)
  • LowerTierImageGenerationRequest (37-39)
  • HigherTierImageGenerationRequest (48-57)
  • LowerTierImageGenerationResponse (42-44)
  • HigherTierImageGenerationResponse (60-67)
backend/src/modules/ai/routes/generation.routes.ts (3)
backend/src/modules/ai/controllers/generation.controller.ts (1)
  • ImageGenerationController (7-29)
backend/src/shared/middleware/validation.middleware.ts (1)
  • validateRequest (5-26)
backend/src/modules/ai/types/generation.types.ts (2)
  • LowerTierImageGenerationRequestSchema (5-18)
  • HigherTierImageGenerationRequestSchema (20-33)
backend/src/modules/ai/routes/summarization.routes.ts (3)
backend/src/modules/ai/controllers/summarization.controller.ts (1)
  • SummarizationController (7-47)
backend/src/shared/middleware/validation.middleware.ts (1)
  • validateRequest (5-26)
backend/src/modules/ai/types/summarization.types.ts (1)
  • SummarizationRequestSchema (5-16)
backend/src/modules/ai/services/imagen/together.service.ts (7)
backend/src/modules/ai/strategy/generation.strategy.ts (1)
  • ImageGenerationStrategy (9-13)
backend/src/modules/ai/utils/ai.utils.ts (1)
  • checkEnvironmentVariables (65-82)
backend/src/modules/ai/config/prompts.ts (1)
  • IMAGE_GENERATION_USER_PROMPT (134-149)
backend/src/shared/config/environment.ts (1)
  • env (29-68)
backend/src/shared/errors/index.ts (1)
  • AppError (1-11)
backend/src/modules/ai/types/generation.types.ts (3)
  • LowerTierImageGenerationRequest (37-39)
  • HigherTierImageGenerationRequest (48-57)
  • LowerTierImageGenerationResponse (42-44)
backend/src/shared/utils/logger.ts (1)
  • logger (28-49)
backend/src/shared/config/environment.ts (1)
backend/src/shared/utils/logger.ts (1)
  • logger (28-49)
backend/src/modules/ai/config/models.ts (2)
backend/src/modules/ai/types/models.types.ts (2)
  • ModelConfig (34-44)
  • GenerationModelConfig (51-59)
backend/src/modules/ai/config/prompts.ts (1)
  • SUMMARY_SYSTEM_PROMPT (1-46)
backend/src/modules/ai/services/generation.service.ts (4)
backend/src/modules/ai/strategy/generation.strategy.ts (1)
  • ImageGenerationStrategy (9-13)
backend/src/modules/ai/utils/ai.utils.ts (1)
  • checkEnvironmentVariables (65-82)
backend/src/shared/errors/index.ts (1)
  • AppError (1-11)
backend/src/modules/ai/types/generation.types.ts (3)
  • LowerTierImageGenerationRequest (37-39)
  • HigherTierImageGenerationRequest (48-57)
  • LowerTierImageGenerationResponse (42-44)
backend/src/modules/ai/utils/ai.utils.ts (2)
backend/src/shared/config/environment.ts (1)
  • env (29-68)
backend/src/shared/errors/index.ts (1)
  • AppError (1-11)
🪛 Shellcheck (0.10.0)
backend/scripts/config.sh

[warning] 21-21: COLOR_CYAN appears unused. Verify use (or export if used externally).

(SC2034)


[warning] 22-22: COLOR_WHITE appears unused. Verify use (or export if used externally).

(SC2034)

🔇 Additional comments (29)
backend/package.json (1)

39-39:

❓ Verification inconclusive

Verify dependency replacement and lockfile update

You’ve replaced @google/generative-ai with @google/genai and added together-ai. Ensure:

  1. All imports of the old package are removed.
  2. The lockfile (package-lock.json/yarn.lock) is updated and committed.
  3. There are no breaking API changes in the new clients.

You can run:

Also applies to: 56-56


🏁 Script executed:

# Check for leftover imports
rg '@google/generative-ai'
rg 'together-ai' -A2

# Install and verify lockfile
npm install
git diff --name-only | grep -E 'package-lock.json|yarn.lock'

Length of output: 1237


🏁 Script executed:

#!/bin/bash
cd backend

# 1. Verify no leftover imports of the old package
rg '@google/generative-ai'

# 2. Confirm together-ai imports are expected
rg 'together-ai' -A2

# 3. Install and check lockfile changes
npm install
git diff --name-only | grep -E 'package-lock.json|yarn.lock'

Length of output: 1690


🏁 Script executed:

#!/bin/bash
cd backend

# 1. Verify that the new Google GenAI client is imported
rg '@google/genai' -A2 src/modules/ai/services/imagen

# 2. Check for lockfile updates after installation
npm install
git diff --name-only | grep -E 'package-lock.json|yarn.lock'

Length of output: 856


🏁 Script executed:

#!/bin/bash
cd backend

# Check for lockfile presence and entries
if [ -f package-lock.json ]; then
  echo "Found package-lock.json"
  echo "🔍 Searching for @google/genai in package-lock.json"
  grep -C2 '"@google/genai"' package-lock.json || echo "❌ No entry for @google/genai"
  echo "🔍 Searching for together-ai in package-lock.json"
  grep -C2 '"together-ai"' package-lock.json || echo "❌ No entry for together-ai"
elif [ -f yarn.lock ]; then
  echo "Found yarn.lock"
  echo "🔍 Searching for @google/genai and together-ai in yarn.lock"
  grep -E '(@google/genai|together-ai)' -C2 yarn.lock || echo "❌ No entries found"
else
  echo "❌ No lockfile detected (package-lock.json or yarn.lock)"
fi

Length of output: 775


Dependency migration verified

  • No remaining imports of @google/generative-ai were found.
  • Imports of the new clients (@google/genai and together-ai) are correctly in place.
  • package-lock.json includes entries for both @google/genai and together-ai, confirming the lockfile was updated and committed.

Please perform a manual review (run existing tests or smoke checks) to ensure there are no breaking API changes in the new clients.

backend/src/modules/ai/services/imagen/index.ts (1)

1-2: Barrel exports look correct

Re-exporting both strategy implementations provides a clean API boundary. This index file aligns with the PR’s modular design.

backend/src/modules/ai/types/index.ts (1)

3-3: LGTM! Clean addition following established patterns.

The new export for generation types follows the existing pattern and enables centralized access to image generation types through the module index.

backend/src/modules/ai/services/index.ts (1)

1-2: LGTM! Good module organization with centralized service exports.

This index file follows the established pattern and provides a clean single entry point for importing AI services.

backend/src/modules/ai/routes/summarization.routes.ts (3)

6-6: LGTM! Variable rename improves clarity.

Renaming the router variable to summarizationRouter provides better clarity and follows naming conventions.


15-19: LGTM! Streaming endpoint follows established patterns.

The new /summarize/stream endpoint correctly:

  • Uses the same validation schema as the standard endpoint
  • Follows the same route structure pattern
  • References the existing summarizeAsStream controller method

21-21: LGTM! Export updated correctly.

The export statement correctly uses the renamed router variable.

backend/src/shared/config/environment.ts (3)

5-5: LGTM! Improved logging consistency.

Replacing console.log with structured logging using the logger utility improves consistency and follows logging best practices.

Also applies to: 17-17


20-20: LGTM! Error message clarity improvement.

The updated error message provides clearer context about the failure to locate the environment file.


46-46: LGTM! New AI provider environment variables added correctly.

The new environment variables properly support the image generation functionality:

  • googleUseVertexAI uses standard boolean conversion pattern
  • togetherKey and togetherBaseUrl support the Together AI provider
  • All additions align with the new AI image generation services

Also applies to: 50-51

backend/src/modules/ai/routes/generation.routes.ts (1)

1-22: LGTM! Well-structured routing implementation.

The router setup is clean and follows good practices:

  • Appropriate separation of single vs multiple generation endpoints
  • Proper validation middleware integration
  • Clear tier-based schema validation
  • Consistent with Express.js patterns
backend/.env.sample (1)

42-44: LGTM! AI configuration variables properly added.

The addition of GEMINI_API_KEY and TOGETHER_API_KEY environment variables correctly supports the new AI image generation and summarization services introduced in this PR.

backend/src/modules/ai/types/summarization.types.ts (2)

7-7: LGTM! Improved validation error messages.

The validation error messages are now more explicit and user-friendly, clearly indicating the constraints on the text field.


36-53: LGTM! Well-structured streaming interfaces.

The new SummarizationStreamResponse and SummarizationStreamChunk interfaces provide proper type safety for streaming functionality. The consistent metadata structure across all response types maintains good design patterns.

backend/src/modules/ai/services/generation.service.ts (2)

9-24: LGTM! Proper constructor validation and strategy pattern implementation.

The constructor correctly validates environment variables for both AI providers and ensures a valid strategy is provided. The error handling with AppError is consistent and informative.


26-41: LGTM! Well-implemented strategy accessors.

The getter and setter methods for the strategy are properly implemented with validation in the setter to prevent invalid strategy assignment.

backend/scripts/config.sh (1)

1-54: LGTM! Well-structured logging utility script.

The script provides excellent standardized logging functionality with:

  • Proper color detection and fallback
  • Appropriate use of stderr for warnings and errors
  • Consistent timestamp formatting
  • Good error handling with set -e

This will improve consistency across backend shell scripts.

🧰 Tools
🪛 Shellcheck (0.10.0)

[warning] 21-21: COLOR_CYAN appears unused. Verify use (or export if used externally).

(SC2034)


[warning] 22-22: COLOR_WHITE appears unused. Verify use (or export if used externally).

(SC2034)

backend/src/modules/ai/services/imagen/google.service.ts (2)

27-27: Verify the use of preview model as default.

The default model is set to Gemini20FlashImageGenPreview which appears to be a preview version. Please confirm this is the intended default model for production use.


61-67:

✅ Verification successful

Verify the Google GenAI API usage.

The code calls genAI.models.generateImages but this API method needs verification. The Google GenAI client might use a different method name or structure.


🌐 Web query:

What is the correct API method for generating images using the @google/genai SDK version 1.4.0?

💡 Result:

To generate images using the @google/genai SDK version 1.4.0, you need to use the generateImages method from the models module of the SDK.

The correct syntax for generating images is:

const response = await client.models.generateImages({
  model: 'imagen-3.0-generate-002',
  prompt: 'Your descriptive prompt here',
  config: {
    numberOfImages: 1,
    // Additional configuration options
  }
});

This method allows you to create images using Google's Imagen model through the Gemini API. Here are the key components of the image generation process:

  1. You need to create a client instance first using the GoogleGenAI class and provide your API key.
  2. The generateImages method is accessed through the models submodule of the client instance.
  3. You must specify the model to use - 'imagen-3.0-generate-002' is a commonly used option.
  4. A text prompt is required to guide the image generation.
  5. Additional configuration parameters can be provided, such as:
    • numberOfImages: The number of images to generate (1-4 images)[5]
    • aspectRatio: Controls the dimensions of the generated image (options include "1:1", "3:4", "4:3", "9:16", and "16:9")[1]
    • personGeneration: Controls whether people can be generated in images[1]

The generated images will be watermarked with SynthID and can be accessed from the response object[1].

Note that for most use cases, you should start with Gemini for image generation, but for specialized tasks where image quality is critical, Imagen is recommended[1].

Citations:


Google GenAI generateImages Usage is Correct
Verified that calling genAI.models.generateImages({ model, prompt, config }) matches the @google/genai SDK v1.4.0 documentation for image generation. No changes required.

backend/src/modules/ai/utils/ai.utils.ts (2)

47-63: Well-implemented environment validation.

The validation for Together AI environment variables is correctly implemented with clear error messages.


65-82: Clean dispatcher pattern implementation.

The environment variable validation dispatcher is well-implemented with proper error handling for unknown providers.

backend/justfile (1)

1-11: Well-structured justfile with good practices.

The justfile follows good practices:

  • Exports configuration script for consistency
  • Provides convenient aliases
  • Includes a default recipe that lists available commands
backend/src/modules/ai/services/summarization.service.ts (3)

20-26: Well-structured service initialization.

Good practices observed:

  • Environment validation at initialization time
  • Proper setup of tiktoken encoding for token counting
  • Clear default model configuration

45-51: Clean token calculation implementation.

The token usage calculation is properly implemented, providing accurate metrics for both prompt and response tokens.


53-120: Excellent refactoring of the summarize method.

The updated implementation shows several improvements:

  • Clean migration to the new GoogleGenAI client
  • Comprehensive error handling with proper error propagation
  • Useful metadata tracking (model, processing time, token count)
  • Clear documentation of the GenAI parameters
backend/src/modules/ai/config/prompts.ts (2)

1-46: Excellent prompt structure for summarization.

The summarization system prompt is well-structured with clear sections, specific requirements, and comprehensive guidelines. The use of XML-like tags improves readability and organization.


71-125: Well-structured image generation system prompt.

The image generation system prompt follows good practices with clear sections for core tasks, requirements, guidelines, prohibitions, and quality standards. The structure promotes consistent output quality.

backend/src/modules/ai/types/models.types.ts (2)

6-7: Approve the new AIModel enum addition.

The addition of Gemini15FlashLite follows consistent naming conventions and extends the existing enum appropriately.


1-1:

✅ Verification successful

Verify the Google GenAI import usage.

The import from @google/genai introduces a dependency that should be verified for compatibility and proper usage.


🏁 Script executed:

#!/bin/bash
# Description: Verify the @google/genai package usage and version
# Expected: Find package.json entry and usage patterns

# Check if the package is listed in dependencies
cat backend/package.json | jq '.dependencies["@google/genai"]'

# Search for usage of the imported types
rg -A 3 "HarmBlockMethod|HarmBlockThreshold|HarmCategory" backend/src/

Length of output: 5976


Import @google/genai is properly declared and utilized

  • backend/package.json lists "@google/genai": "^1.4.0".
  • HarmBlockMethod, HarmBlockThreshold, and HarmCategory are imported in backend/src/modules/ai/types/models.types.ts and consumed in backend/src/modules/ai/config/models.ts.
  • No compatibility or usage issues found; no changes required.

Comment on lines +11 to +12
ports:
- "5433:5433"
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix PostgreSQL port mapping

The container’s default Postgres port is 5432, so mapping "5433:5433" won’t expose the database. Change to map host port 5433 to container port 5432:

 ports:
-  - "5433:5433"
+  - "5433:5432"
🤖 Prompt for AI Agents
In backend/docker-compose.yml around lines 11 to 12, the port mapping for
PostgreSQL is incorrect because it maps host port 5433 to container port 5433,
but the container uses the default port 5432. Update the port mapping to
"5433:5432" to expose the container's PostgreSQL service correctly on host port
5433.

Comment on lines +22 to +28
generateImageMultiple = async (req: Request, res: Response, next: NextFunction) => {
try {
return [];
} catch (error) {
next(error);
}
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Implement the actual multiple image generation logic.

Similar to the single generation method, this placeholder implementation needs to be completed with actual service calls and proper response handling.

 generateImageMultiple = async (req: Request, res: Response, next: NextFunction) => {
     try {
-        return [];
+        const requestData = req.body;
+        const results = await this.service.generateMultiple(requestData);
+        
+        logger.info('Successfully generated multiple images', {
+            promptLength: requestData.prompt.length,
+            imageCount: results.length,
+        });
+        
+        res.json(createSuccessResponse(results));
     } catch (error) {
         next(error);
     }
 };
🤖 Prompt for AI Agents
In backend/src/modules/ai/controllers/generation.controller.ts around lines 22
to 28, the generateImageMultiple method currently returns an empty array as a
placeholder. Replace this with the actual logic to generate multiple images by
calling the appropriate service method, handling the request data, and sending
the generated images in the response. Ensure proper error handling by keeping
the try-catch structure and calling next(error) on failure.

Comment on lines +14 to +20
generateImageSingle = async (req: Request, res: Response, next: NextFunction) => {
try {
return [];
} catch (error) {
next(error);
}
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Implement the actual image generation logic.

The method currently returns an empty array, which doesn't match the expected response type and provides no functionality. The instantiated service should be used to process the request.

 generateImageSingle = async (req: Request, res: Response, next: NextFunction) => {
     try {
-        return [];
+        const requestData = req.body;
+        const result = await this.service.generate(requestData);
+        
+        logger.info('Successfully generated single image', {
+            promptLength: requestData.prompt.length,
+            model: result.metadata?.model,
+        });
+        
+        res.json(createSuccessResponse(result));
     } catch (error) {
         next(error);
     }
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
generateImageSingle = async (req: Request, res: Response, next: NextFunction) => {
try {
return [];
} catch (error) {
next(error);
}
};
generateImageSingle = async (req: Request, res: Response, next: NextFunction) => {
try {
const requestData = req.body;
const result = await this.service.generate(requestData);
logger.info('Successfully generated single image', {
promptLength: requestData.prompt.length,
model: result.metadata?.model,
});
res.json(createSuccessResponse(result));
} catch (error) {
next(error);
}
};
🤖 Prompt for AI Agents
In backend/src/modules/ai/controllers/generation.controller.ts around lines 14
to 20, the generateImageSingle method currently returns an empty array instead
of implementing the actual image generation logic. Replace the placeholder
return with code that uses the instantiated image generation service to process
the request data and return the generated image(s) in the response, ensuring the
output matches the expected response type.

Comment on lines +43 to +45
async generate(
request: LowerTierImageGenerationRequest | HigherTierImageGenerationRequest
): Promise<LowerTierImageGenerationResponse | HigherTierImageGenerationRequest> {
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix the incorrect return type in generate method.

The return type should be LowerTierImageGenerationResponse | HigherTierImageGenerationResponse instead of LowerTierImageGenerationResponse | HigherTierImageGenerationRequest.

async generate(
    request: LowerTierImageGenerationRequest | HigherTierImageGenerationRequest
-): Promise<LowerTierImageGenerationResponse | HigherTierImageGenerationRequest> {
+): Promise<LowerTierImageGenerationResponse | HigherTierImageGenerationResponse> {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async generate(
request: LowerTierImageGenerationRequest | HigherTierImageGenerationRequest
): Promise<LowerTierImageGenerationResponse | HigherTierImageGenerationRequest> {
async generate(
request: LowerTierImageGenerationRequest | HigherTierImageGenerationRequest
): Promise<LowerTierImageGenerationResponse | HigherTierImageGenerationResponse> {
🤖 Prompt for AI Agents
In backend/src/modules/ai/services/generation.service.ts around lines 43 to 45,
the generate method's return type is incorrectly specified as
LowerTierImageGenerationResponse | HigherTierImageGenerationRequest. Update the
return type to LowerTierImageGenerationResponse |
HigherTierImageGenerationResponse to correctly reflect the possible response
types returned by the method.

Comment on lines +82 to +100
// TODO: Finish implementation for generate method in GeminiImageGenerationService

} catch (error) {
if (error instanceof AppError) {
throw error;
} else {
logger.error(
APP_ERROR_SOURCE,
'An unexpected error occurred during image generation.',
error
);
throw new AppError(
500,
'An unexpected error occurred during image generation. Please try again later.',
APP_ERROR_SOURCE
);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Complete the implementation or throw an error.

The method has a TODO comment and doesn't return anything, which will cause a runtime error since the return type is a Promise.

The method needs to either:

  1. Return a proper response object
  2. Throw an error indicating it's not implemented

Would you like me to help implement the complete logic or create an issue to track this TODO?

🤖 Prompt for AI Agents
In backend/src/modules/ai/services/imagen/google.service.ts around lines 82 to
100, the generate method is incomplete and currently does not return any value,
which will cause a runtime error due to its Promise return type. To fix this,
either implement the full logic to return the expected response object or
explicitly throw a "Not Implemented" error to indicate the method is unfinished.
This ensures the method adheres to its return type contract and prevents runtime
issues.

Comment on lines +150 to +164
const stream = [];
for await (const chunk of result) {
const summaryChunk = chunk.text;

if (!summaryChunk) {
throw new AppError(
500,
'Failed to generate summary stream, the model returned an empty response which was unexpected.',
APP_ERROR_SOURCE
);
}

logger.debug('Received chunk from summarization stream', { summaryChunk });
stream.push(summaryChunk);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider true streaming implementation.

The current implementation collects all chunks in an array before returning, which defeats the purpose of streaming. For true streaming support, consider yielding chunks as they arrive.

Consider implementing an async generator that yields chunks:

async *summarizeStream(request: SummarizationRequest): AsyncGenerator<string, SummarizationStreamResponse> {
  const startTime = Date.now();
  const modelType = request.options?.model || this.defaultModelType;
  
  // ... setup code ...
  
  const chunks: string[] = [];
  for await (const chunk of result) {
    const summaryChunk = chunk.text;
    if (!summaryChunk) {
      throw new AppError(500, 'Empty chunk received', APP_ERROR_SOURCE);
    }
    
    chunks.push(summaryChunk);
    yield summaryChunk; // Yield chunk immediately
  }
  
  // Return metadata after streaming completes
  return {
    stream: chunks,
    metadata: {
      model: modelType,
      processingTime: Date.now() - startTime,
      tokenCount: this.calculateTokenUsage(formattedPrompt, chunks.join(''))
    }
  };
}

This allows the controller to stream responses to the client in real-time.

🤖 Prompt for AI Agents
In backend/src/modules/ai/services/summarization.service.ts around lines 150 to
164, the current code collects all summary chunks into an array before
returning, which prevents true streaming. Refactor the method into an async
generator that yields each chunk as it arrives using "yield summaryChunk" inside
the loop. Accumulate chunks in an array for metadata calculation, then return
the metadata and full stream after iteration completes. This change enables
real-time streaming of summary chunks to the client.

Comment on lines +36 to +44
// TODO: Implement interface LowerTierImageGenerationRequest
export interface LowerTierImageGenerationRequest {
prompt: string;
}

// TODO: Implement interface LowerTierImageGenerationResponse
export interface LowerTierImageGenerationResponse {
prompt: string;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Complete the incomplete interface implementations.

The LowerTierImageGenerationRequest and LowerTierImageGenerationResponse interfaces are marked as TODOs and are incomplete. They don't match the complexity of their corresponding Zod schemas.

Apply this diff to properly implement the interfaces:

-// TODO: Implement interface LowerTierImageGenerationRequest
 export interface LowerTierImageGenerationRequest {
   prompt: string;
+  options?: {
+    model?: AIGenerationModel;
+    width?: number;
+    height?: number;
+    steps?: number;
+    disable_safety_checker?: boolean;
+  };
 }

-// TODO: Implement interface LowerTierImageGenerationResponse
 export interface LowerTierImageGenerationResponse {
-  prompt: string;
+  imageUrl: string;
+  metadata?: {
+    model: string;
+    processingTime: number;
+  };
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// TODO: Implement interface LowerTierImageGenerationRequest
export interface LowerTierImageGenerationRequest {
prompt: string;
}
// TODO: Implement interface LowerTierImageGenerationResponse
export interface LowerTierImageGenerationResponse {
prompt: string;
}
export interface LowerTierImageGenerationRequest {
prompt: string;
options?: {
model?: AIGenerationModel;
width?: number;
height?: number;
steps?: number;
disable_safety_checker?: boolean;
};
}
export interface LowerTierImageGenerationResponse {
imageUrl: string;
metadata?: {
model: string;
processingTime: number;
};
}
🤖 Prompt for AI Agents
In backend/src/modules/ai/types/generation.types.ts between lines 36 and 44, the
interfaces LowerTierImageGenerationRequest and LowerTierImageGenerationResponse
are incomplete and only contain a prompt string. Update these interfaces to
fully match the corresponding Zod schemas by adding all required properties and
types as defined in those schemas, ensuring the interfaces accurately represent
the expected data structure.

Comment on lines +63 to +70
/**
* TODO: Refactor this prompt later to be more structured and clear.
*
* Similar to the image generation prompt below, this one is also a bit
* scuffed in terms of how it handles user tiers. It should be handled
* in the service layer, not passed to the prompt for the AI to figure
* out whether to generate a high or low resolution image.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Address the architectural concern about user tier handling.

The TODO comments correctly identify that user tier handling should be moved from the prompt layer to the service layer. This is an important architectural decision that affects maintainability and separation of concerns.

The current approach of passing user tier information to the AI prompt creates tight coupling between business logic and AI prompts. Would you like me to help design a service layer solution that handles tier-based logic before prompt generation?

Let me verify how the current tier-based logic is implemented across the codebase:

Also applies to: 127-133


🏁 Script executed:

#!/bin/bash
# Description: Search for user tier handling patterns in the AI module
# Expected: Find current implementations that need refactoring

# Search for tier-related logic in AI services
rg -A 5 -B 5 "tier|Tier" backend/src/modules/ai/

# Search for prompt template usage
rg -A 3 "IMAGE_GENERATION_USER_PROMPT" backend/src/modules/ai/

Length of output: 20995


Refactor user-tier logic out of AI prompts

The tier-based branching belongs in the service layer, not embedded in the prompt template. Move all “paid vs. free” resolution decisions into your image-generation services and supply only concrete values to the prompt.

• backend/src/modules/ai/config/prompts.ts

  • Remove the <user_tier> section and any “If paid, generate high-res… if free, generate standard-res…” text from IMAGE_GENERATION_USER_PROMPT.
  • Replace with a generic <resolution>{resolution}</resolution> placeholder and neutral instructions.
export const IMAGE_GENERATION_USER_PROMPT = `
Please generate an image based on the following description.

<image_description>
{description}
</image_description>

-<user_tier>
-{userTier}
-</user_tier>
-<instructions>
-If the user is a paid user, generate a high-resolution image with enhanced quality and detail.
-If the user is a free user, generate a standard resolution image.
-Ensure the image is appropriate and follows content guidelines.
-</instructions>
+<resolution>
+{resolution}
+</resolution>
+<instructions>
+Create an image that accurately represents the provided description, following all content guidelines.
+</instructions>
`;

• backend/src/modules/ai/services/imagen/together.service.ts
• backend/src/modules/ai/services/imagen/google.service.ts

  • In each generate() implementation, branch on request type (LowerTier… vs. HigherTier…) to compute a resolution string or width/height settings.
  • Pass this concrete resolution into the prompt template (e.g. prompt.format({ description, resolution, … })) instead of userTier.

Optional improvement: Consolidate LowerTier/HigherTier schemas into a single ImageGenerationRequest with a tier enum and shared options, then centralize the tier→resolution mapping in one helper.

This separation will decouple business logic from prompt content and make future changes simpler.

🤖 Prompt for AI Agents
In backend/src/modules/ai/config/prompts.ts around lines 63 to 70, refactor the
IMAGE_GENERATION_USER_PROMPT by removing all user tier references and
conditional text about paid vs. free resolution. Replace these with a generic
resolution placeholder like <resolution>{resolution}</resolution> and neutral
instructions. Then, in
backend/src/modules/ai/services/imagen/together.service.ts and
google.service.ts, move the tier-based logic to the generate() methods by
branching on the request type to determine the concrete resolution string or
dimensions. Pass this resolved value into the prompt formatting instead of user
tier. Optionally, unify tier schemas and centralize tier-to-resolution mapping
in a helper to cleanly separate business logic from prompt content.

Comment on lines +141 to +149
<user_tier>
{userTier}
</user_tier>
Remember to maintain clarity and conciseness while capturing all essential information.`;
<instructions>
Create an image that accurately represents the provided description. If the user is a paid user,
generate a high-resolution image with enhanced quality and detail. If the user is a free user,
generate a standard resolution image. Ensure the image is appropriate and follows content guidelines.
</instructions>`;
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove hardcoded tier-based logic from the prompt.

The image generation user prompt contains hardcoded logic for handling paid vs free users, which violates separation of concerns and makes the system less flexible.

Apply this diff to remove tier-specific logic from the prompt:

 export const IMAGE_GENERATION_USER_PROMPT = `
 Please generate an image based on the following description and user requirements.

 <image_description>
 {description}
 </image_description>

-<user_tier>
-{userTier}
-</user_tier>

 <instructions>
-Create an image that accurately represents the provided description. If the user is a paid user, 
-generate a high-resolution image with enhanced quality and detail. If the user is a free user, 
-generate a standard resolution image. Ensure the image is appropriate and follows content guidelines.
+Create an image that accurately represents the provided description with the specified quality settings. 
+Ensure the image is appropriate and follows content guidelines.
 </instructions>`;

The service layer should handle tier-based resolution and quality decisions before calling the AI service.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<user_tier>
{userTier}
</user_tier>
Remember to maintain clarity and conciseness while capturing all essential information.`;
<instructions>
Create an image that accurately represents the provided description. If the user is a paid user,
generate a high-resolution image with enhanced quality and detail. If the user is a free user,
generate a standard resolution image. Ensure the image is appropriate and follows content guidelines.
</instructions>`;
export const IMAGE_GENERATION_USER_PROMPT = `
Please generate an image based on the following description and user requirements.
<image_description>
{description}
</image_description>
<instructions>
Create an image that accurately represents the provided description with the specified quality settings.
Ensure the image is appropriate and follows content guidelines.
</instructions>`;
🤖 Prompt for AI Agents
In backend/src/modules/ai/config/prompts.ts around lines 141 to 149, the prompt
includes hardcoded logic differentiating image generation instructions based on
user tier, which breaks separation of concerns. Remove any tier-specific
conditions or instructions from the prompt text so it only contains generic
image generation instructions. Instead, ensure that the service layer outside
this prompt handles all decisions related to image resolution and quality based
on user tier before invoking the AI service.

Comment on lines +46 to +59
export interface ImageLora {
path?: string;
scale: number;
}

export interface GenerationModelConfig {
steps?: number;
width?: number;
height?: number;
n?: number;
responseFormat?: string;
image_loras?: ImageLora[];
disableSafetyChecker?: boolean;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add validation constraints to GenerationModelConfig.

The GenerationModelConfig interface lacks validation constraints that could prevent invalid configurations.

Consider adding JSDoc comments with constraints and potentially using branded types:

 export interface GenerationModelConfig {
+  /** Number of inference steps (typically 1-100) */
   steps?: number;
+  /** Image width in pixels (must be positive, typically 256-2048) */
   width?: number;
+  /** Image height in pixels (must be positive, typically 256-2048) */
   height?: number;
+  /** Number of images to generate (typically 1-10) */
   n?: number;
+  /** Response format (e.g., 'url', 'b64_json') */
   responseFormat?: string;
   image_loras?: ImageLora[];
   disableSafetyChecker?: boolean;
 }

Consider creating Zod schemas for runtime validation of these configurations.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface ImageLora {
path?: string;
scale: number;
}
export interface GenerationModelConfig {
steps?: number;
width?: number;
height?: number;
n?: number;
responseFormat?: string;
image_loras?: ImageLora[];
disableSafetyChecker?: boolean;
}
export interface ImageLora {
path?: string;
scale: number;
}
export interface GenerationModelConfig {
/** Number of inference steps (typically 1-100) */
steps?: number;
/** Image width in pixels (must be positive, typically 256-2048) */
width?: number;
/** Image height in pixels (must be positive, typically 256-2048) */
height?: number;
/** Number of images to generate (typically 1-10) */
n?: number;
/** Response format (e.g., 'url', 'b64_json') */
responseFormat?: string;
image_loras?: ImageLora[];
disableSafetyChecker?: boolean;
}
🤖 Prompt for AI Agents
In backend/src/modules/ai/types/models.types.ts between lines 46 and 59, the
GenerationModelConfig interface lacks validation constraints. Add JSDoc comments
specifying valid ranges or allowed values for each property to document
constraints clearly. Additionally, define branded types if needed to enforce
stricter typing. For runtime validation, create corresponding Zod schemas that
validate the shape and constraints of GenerationModelConfig objects before use.

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