Member Junction
    Preparing search index...

    Module @memberjunction/ai-recommendations - v5.49.0

    @memberjunction/ai-recommendations

    A provider-based recommendation engine for MemberJunction. Manages recommendation runs, delegates to pluggable providers via the class factory, and tracks results through Recommendation, Recommendation Run, and Recommendation Item entities.

    graph TD
        subgraph Engine["@memberjunction/ai-recommendations"]
            REB["RecommendationEngineBase
    (singleton BaseEngine)"] RPB["RecommendationProviderBase
    (abstract)"] RR["RecommendationRequest<T>"] RRES["RecommendationResult"] end subgraph Providers["Registered Providers"] P1["Provider A"] P2["Provider B"] end subgraph MJEntities["MemberJunction Entities"] RP["Recommendation Providers"] RUN["Recommendation Runs"] REC["Recommendations"] RI["Recommendation Items"] LIST["Lists / List Details"] end subgraph MJCore["MemberJunction Core"] BE["BaseEngine"] CF["ClassFactory"] MD["Metadata"] end REB -->|extends| BE REB -->|discovers| CF CF -->|creates| P1 CF -->|creates| P2 P1 -->|extends| RPB P2 -->|extends| RPB REB --> RP REB --> RUN RPB --> REC RPB --> RI REB --> LIST style Engine fill:#2d6a9f,stroke:#1a4971,color:#fff style Providers fill:#2d8659,stroke:#1a5c3a,color:#fff style MJEntities fill:#b8762f,stroke:#8a5722,color:#fff style MJCore fill:#7c5295,stroke:#563a6b,color:#fff
    npm install @memberjunction/ai-recommendations
    

    This package provides the framework for running recommendations in MemberJunction. It follows the engine/provider pattern used throughout the platform:

    1. RecommendationEngineBase -- a singleton engine (extending BaseEngine) that loads provider metadata, selects a provider, creates Recommendation Run tracking records, and delegates the actual recommendation logic
    2. RecommendationProviderBase -- an abstract class that concrete providers implement to generate recommendations for each source record
    3. RecommendationRequest/RecommendationResult -- typed request and response objects that flow through the pipeline

    Providers are discovered at runtime through MemberJunction's ClassFactory using @RegisterClass(RecommendationProviderBase, 'ProviderName').

    sequenceDiagram
        participant Caller
        participant Engine as RecommendationEngineBase
        participant CF as ClassFactory
        participant Provider as RecommendationProvider
        participant DB as MJ Database
    
        Caller->>Engine: Recommend(request)
        Engine->>Engine: TryThrowIfNotLoaded()
    
        alt Provider specified
            Engine->>Engine: Use request.Provider
        else No provider
            Engine->>Engine: Use first available
        end
    
        Engine->>Engine: GetRecommendationEntities(request)
    
        alt From List
            Engine->>DB: Load List + List Details
            Engine->>DB: Load entity records by IDs
        else From EntityAndRecordsInfo
            Engine->>DB: Load records by entity name + IDs
        else Pre-built
            Engine->>Engine: Validate Recommendations array
        end
    
        Engine->>DB: Create Recommendation Run (Status: In Progress)
    
        opt CreateErrorList = true
            Engine->>DB: Create error tracking List
        end
    
        Engine->>CF: CreateInstance(provider.Name)
        CF-->>Engine: Provider instance
    
        Engine->>Provider: Recommend(request)
    
        loop For each recommendation
            Provider->>Provider: Call external API
            Provider->>DB: SaveRecommendation + Items
        end
    
        Provider-->>Engine: RecommendationResult
    
        Engine->>DB: Update Run (Completed/Error)
        Engine-->>Caller: RecommendationResult
    

    A singleton engine that manages the recommendation lifecycle.

    import { RecommendationEngineBase } from '@memberjunction/ai-recommendations';

    // Access the singleton
    const engine = RecommendationEngineBase.Instance;

    // Initialize (loads Recommendation Providers metadata)
    await engine.Config(false, contextUser);

    // Run recommendations
    const result = await engine.Recommend(request);

    Key properties and methods:

    Member Description
    Instance Static getter for the singleton instance
    RecommendationProviders Array of RecommendationProviderEntity loaded from metadata
    Config(forceRefresh?, contextUser?, provider?) Loads provider metadata into cache
    Recommend<T>(request) Runs the full recommendation pipeline

    Abstract base class for implementing recommendation providers.

    classDiagram
        class RecommendationProviderBase {
            <>
            -_md : Metadata
            -_ContextUser : UserInfo
            +ContextUser : UserInfo
            +Recommend(request)* RecommendationResult
            #SaveRecommendation(rec, runID, items) boolean
        }
    
        class ConcreteProvider {
            +Recommend(request) RecommendationResult
        }
    
        RecommendationProviderBase <|-- ConcreteProvider
    
        style RecommendationProviderBase fill:#2d6a9f,stroke:#1a4971,color:#fff
        style ConcreteProvider fill:#2d8659,stroke:#1a5c3a,color:#fff
    

    The SaveRecommendation helper method handles:

    1. Setting the RecommendationRunID on the recommendation entity
    2. Saving the recommendation record
    3. Linking and saving all RecommendationItemEntity records

    The request object supports three ways to specify source records:

    graph TD
        RR["RecommendationRequest"]
        OPT1["Recommendations[]
    Pre-built entities"] OPT2["EntityAndRecordsInfo
    Entity name + Record IDs"] OPT3["ListID
    MJ List reference"] RR --> OPT1 RR --> OPT2 RR --> OPT3 style RR fill:#2d6a9f,stroke:#1a4971,color:#fff style OPT1 fill:#2d8659,stroke:#1a5c3a,color:#fff style OPT2 fill:#2d8659,stroke:#1a5c3a,color:#fff style OPT3 fill:#2d8659,stroke:#1a5c3a,color:#fff
    Field Type Description
    Recommendations RecommendationEntity[] Pre-built unsaved recommendation entities
    EntityAndRecordsInfo { EntityName, RecordIDs } Entity name and array of record IDs to process
    ListID string ID of a MJ List whose details become the source records
    Provider RecommendationProviderEntity Specific provider to use (defaults to first available)
    CurrentUser UserInfo User context
    Options T Generic additional options passed to the provider
    CreateErrorList boolean Whether to create an error tracking list
    RunID string Set automatically by the engine
    ErrorListID string Set automatically if error list is created
    class RecommendationResult {
    Request: RecommendationRequest;
    RecommendationRun?: RecommendationRunEntity;
    RecommendationItems?: RecommendationItemEntity[];
    Success: boolean;
    ErrorMessage: string;

    AppendWarning(message: string): void; // Adds warning without setting Success=false
    AppendError(message: string): void; // Adds error and sets Success=false
    GetErrorMessages(): string[]; // Splits ErrorMessage into array
    }
    import { RecommendationEngineBase } from '@memberjunction/ai-recommendations';
    import { RecommendationRequest } from '@memberjunction/ai-recommendations';

    const engine = RecommendationEngineBase.Instance;
    await engine.Config(false, contextUser);

    const request = new RecommendationRequest();
    request.ListID = 'list-uuid';
    request.CurrentUser = contextUser;
    request.CreateErrorList = true;

    const result = await engine.Recommend(request);

    if (result.Success) {
    console.log(`Generated ${result.RecommendationItems?.length ?? 0} items`);
    } else {
    console.error(result.ErrorMessage);
    }
    const request = new RecommendationRequest();
    request.EntityAndRecordsInfo = {
    EntityName: 'Products',
    RecordIDs: ['id-1', 'id-2', 'id-3']
    };
    request.CurrentUser = contextUser;

    const result = await engine.Recommend(request);
    import { RecommendationProviderBase } from '@memberjunction/ai-recommendations';
    import { RecommendationRequest, RecommendationResult } from '@memberjunction/ai-recommendations';
    import { RegisterClass } from '@memberjunction/global';
    import { Metadata } from '@memberjunction/core';
    import { RecommendationItemEntity } from '@memberjunction/core-entities';

    @RegisterClass(RecommendationProviderBase, 'My Recommendation Provider')
    export class MyProvider extends RecommendationProviderBase {
    async Recommend(request: RecommendationRequest): Promise<RecommendationResult> {
    const result = new RecommendationResult(request);
    const md = new Metadata();

    for (const rec of request.Recommendations) {
    // Call your recommendation API/algorithm
    const suggestions = await this.getSuggestions(rec.SourceEntityRecordID);

    const items: RecommendationItemEntity[] = [];
    for (const suggestion of suggestions) {
    const item = await md.GetEntityObject<RecommendationItemEntity>(
    'Recommendation Items', request.CurrentUser
    );
    item.NewRecord();
    item.DestinationEntityID = suggestion.entityID;
    item.DestinationEntityRecordID = suggestion.recordID;
    item.MatchProbability = suggestion.score;
    items.push(item);
    }

    await this.SaveRecommendation(rec, request.RunID, items);
    }

    return result;
    }

    private async getSuggestions(recordID: string): Promise<Suggestion[]> {
    // Your recommendation logic here
    return [];
    }
    }
    erDiagram
        RECOMMENDATION_PROVIDERS {
            string ID PK
            string Name
            string Description
        }
    
        RECOMMENDATION_RUNS {
            string ID PK
            string RecommendationProviderID FK
            string RunByUserID FK
            datetime StartDate
            string Status
            string Description
        }
    
        RECOMMENDATIONS {
            string ID PK
            string RecommendationRunID FK
            string SourceEntityID FK
            string SourceEntityRecordID
        }
    
        RECOMMENDATION_ITEMS {
            string ID PK
            string RecommendationID FK
            string DestinationEntityID FK
            string DestinationEntityRecordID
            float MatchProbability
        }
    
        LISTS {
            string ID PK
            string Name
            string EntityID FK
            string UserID FK
        }
    
        RECOMMENDATION_PROVIDERS ||--o{ RECOMMENDATION_RUNS : has
        RECOMMENDATION_RUNS ||--o{ RECOMMENDATIONS : contains
        RECOMMENDATIONS ||--o{ RECOMMENDATION_ITEMS : produces
    
    Package Purpose
    @memberjunction/core BaseEngine, Metadata, RunView, UserInfo, LogStatus
    @memberjunction/core-entities RecommendationEntity, RecommendationRunEntity, RecommendationItemEntity, RecommendationProviderEntity, ListEntity
    @memberjunction/global MJGlobal class factory for provider discovery
    # Build
    npm run build

    # Development mode
    npm run start

    ISC

    Classes

    RecommendationEngineBase
    RecommendationProviderBase
    RecommendationRequest
    RecommendationResult