Skip to content

Latest commit

 

History

History
247 lines (191 loc) · 7.75 KB

README.md

File metadata and controls

247 lines (191 loc) · 7.75 KB

Recombee API Client

A Go client (SDK) for easy use of the Recombee recommendation API.

If you don't have an account at Recombee yet, you can create a free account here.

Documentation of the API can be found at docs.recombee.com.

Installation

Run the following command in your Go project:

go get github.com/recombee/go-api-client/[email protected]

Examples

Basic example

The following example shows how to:

  • Send many interactions within a single Batch request
  • Request recommendations for a user using RecommendItemsToUser and RecommendNextItems endpoints
package main

import (
    "fmt"
    "math/rand"
    "os"

    "github.com/recombee/go-api-client/v4/recombee"
    "github.com/recombee/go-api-client/v4/recombee/requests"
)

func main() {
    client, err := recombee.NewRecombeeClient("your-database-id", "db-private-token", "us-west")
    if err != nil {
        fmt.Println(err)
        panic(err)
    }

    const numItemsAndUsers = 100
    const probabilityInteracted = 0.1

    var addDetailViewInteractions []requests.Request
    for i := 0; i < numItemsAndUsers; i++ {
        for j := 0; j < numItemsAndUsers; j++ {
            if rand.Float64() < probabilityInteracted {
                userId := fmt.Sprintf("user-%d", i)
                itemId := fmt.Sprintf("item-%d", j)

                request := client.NewAddDetailView(userId, itemId).SetCascadeCreate(true)
                addDetailViewInteractions = append(addDetailViewInteractions, request)
            }
        }
    }

    fmt.Println("Send all interactions in Batch")
    batchRes, err := client.NewBatch(addDetailViewInteractions).Send()
    if err != nil {
        fmt.Println(err)
        panic(err)
    }

    fmt.Println(batchRes) // Contains responses for all requests

    // Get 5 recommendations for user 'user-25'
    recommendReq := client.NewRecommendItemsToUser("user-25", 5).SetCascadeCreate(true)
    recommendRes, err := recommendReq.Send()
    if err != nil {
        fmt.Println(err)
        panic(err)
    }

    fmt.Println("Recommended items:")
    for _, rec := range recommendRes.Recomms {
        fmt.Println(rec.Id)
    }

    // User scrolled down - get next 3 recommended items
    fmt.Println("Next recommended items:")
    recommendNextRes, err := client.NewRecommendNextItems(recommendRes.RecommId, 3).Send()
    if err != nil {
        fmt.Println(err)
        panic(err)
    }

    for _, rec := range recommendNextRes.Recomms {
        fmt.Println(rec.Id)
    }
}

See examples/batch for an extended example of using the Batch requests.

Using property values

The second example shows how to:

  • Specify the properties (columns) of the items catalog using AddItemProperty requests
  • Upload their values for all the items using SetItemValues requests in a Batch
  • Get recommendations based on an item using RecommendItemsToItem
  • Search items using SearchItems
package main

import (
    "context"
    "fmt"
    "github.com/recombee/go-api-client/v4/recombee"
    "github.com/recombee/go-api-client/v4/recombee/requests"
    "math/rand"
    "os"
    "time"
)

func main() {
    client, err := recombee.NewRecombeeClient("your-database-id", "db-private-token", "us-west")
    if err != nil {
        fmt.Println(err)
        panic(err)
    }

    // Add item properties
    // Properties are the columns of the items catalogs
    properties := []struct {
        propertyName string
        propertyType string
    }{
        {"price", "double"},
        {"num-cores", "int"},
        {"description", "string"},
        {"image", "image"},
    }

    for _, p := range properties {
        if _, err := client.NewAddItemProperty(p.propertyName, p.propertyType).Send(); err != nil {
            fmt.Println(err)
            panic(err)
        }
    }

    // Prepare and send a catalog of computers
    const numItems = 100
    requestsBatch := make([]requests.Request, numItems)

    for i := 0; i < numItems; i++ {
        itemId := fmt.Sprintf("computer-%d", i)
        requestsBatch[i] = client.NewSetItemValues(itemId, map[string]interface{}{
            "price":       600.0 + 400*rand.Float64(),
            "num-cores":   1 + rand.Intn(7),
            "description": "Great computer",
            "image":       fmt.Sprintf("http://examplesite.com/products/%s.jpg", itemId),
        }).SetCascadeCreate(true)
    }

    if _, err := client.NewBatch(requestsBatch).Send(); err != nil {
        fmt.Println(err)
        panic(err)
    }

    // Simulate random purchases
    const probabilityPurchased = 0.02
    var addPurchaseRequests []requests.Request

    for i := 0; i < numItems; i++ {
        for j := 0; j < numItems; j++ {
            if rand.Float64() < probabilityPurchased {
                userId := fmt.Sprintf("user-%d", i)
                itemId := fmt.Sprintf("computer-%d", j)
                addPurchaseRequests = append(addPurchaseRequests, client.NewAddPurchase(userId, itemId).SetCascadeCreate(true))
            }
        }
    }

    // Send the Batch request with custom timeout
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
    defer cancel()

    if _, err := client.NewBatch(addPurchaseRequests).SendWithContext(ctx); err != nil {
        fmt.Println(err)
        panic(err)
    }

    // Request recommendations with a set scenario
    // Behavior of the recommendations is configured per scenario in the Recombee Admin UI
    req := client.NewRecommendItemsToItem("computer-6", "user-42", 5).SetScenario("product_detail")

    recommRes, err := req.Send()
    if err != nil {
        panic(err)
    }
    fmt.Println("Recommended items:")
    for _, rec := range recommRes.Recomms {
        fmt.Println(rec.Id)
    }

    // Recommend items with at least 3 processor cores (dynamic filter), return property values of the items
    req = client.NewRecommendItemsToItem("computer-6", "user-42", 5)
    req = req.SetFilter("'num-cores'>=3").SetReturnProperties(true)
    recommRes, err = req.Send()
    fmt.Println("\nRecommended items with at least 3 cores:")
    for _, rec := range recommRes.Recomms {
        fmt.Println(rec.Id)
        fmt.Println(rec.Values)
    }

    // Perform a search using "computers" query
    searchResponse, err := client.NewSearchItems("user-42", "computers", 5).Send()

    if err != nil {
        panic(err)
    }
    fmt.Println("\nSearch matches: %s", searchResponse.Recomms)
}

Sending Requests

A request can be sent to the Recombee API using the Send() method.

If you want to provide your own context.Context (e.g. to set your custom timeout for the request) call the SendWithContext(ctx context.Context) method.

RecombeeClient Initialization

The RecombeeClient can be created using the NewRecombeeClient(...) function, as per previous examples.

If you want to provide your own http.Client use NewRecombeeClientWithOptions:

    region := "ap-se"
    options := recombee.ClientOptions{Region: &region, HttpClient: &myHttpClient}
    client, err := recombee.NewRecombeeClientWithOptions("your-database-id", "db-private-token", options)

Custom Errors

Various errors can occur while processing the request, for example, because of adding an already existing item or submitting interaction of a nonexistent user without cascadeCreate set to true. These errors lead to returning the errors.ResponseError by the Send method.

Another reason for producing an error is a timeout, yielding errors.TimeoutError.

We are doing our best to provide the fastest and most reliable service, but production-level applications shall implement a fallback solution since errors can always happen. The fallback might be, for example, showing the most popular items from the current category, or not displaying recommendations at all.