| --- |
| title: Quick Start - Product Ranking Engine Template |
| --- |
| |
| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| ## Overview |
| |
| This engine template sorts a list of products for a user based on his/her preference. This is ideal for personalizing the display order of product page, catalog, or menu items if you have large number of options. It creates engagement and early conversion by placing products that a user prefers on the top. |
| |
| ## Usage |
| |
| ### Event Data Requirements |
| |
| By default, this template takes the following data from Event Server as Training Data: |
| |
| - user *$set* events |
| - item *$set* events |
| - Users' *view* item events |
| |
| INFO: This template can easily be customized to consider more user events such as *buy*, *rate* and *like*. |
| |
| ### Input Query |
| |
| - UserID |
| - List of ItemIDs, which are the products to be ranked |
| |
| ### Output PredictedResult |
| |
| - a ranked list of recommended itemIDs |
| |
| |
| ## 1. Install and Run PredictionIO |
| |
| <%= partial 'shared/quickstart/install' %> |
| |
| ## 2. Create a new Engine from an Engine Template |
| |
| <%= partial 'shared/quickstart/create_engine', locals: { engine_name: 'MyProductRanking', template_name: 'Product Ranking Engine Template', template_repo: 'PredictionIO/template-scala-parallel-productranking' } %> |
| |
| ## 3. Generate an App ID and Access Key |
| |
| <%= partial 'shared/quickstart/create_app' %> |
| |
| ## 4. Collecting Data |
| |
| Next, let's collect some training data for the app of this Engine. By default, |
| the Product Ranking Engine Template supports 2 types of entities: **user** and |
| **item**, and event **view**. A user can view an item. This template requires '$set' user event, '$set' item event and user-view-item events. |
| |
| <%= partial 'shared/quickstart/collect_data' %> |
| |
| For example, when a new user with id "u0" is created in your app on time `2014-11-02T09:39:45.618-08:00` (current time will be used if eventTime is not specified), you can send a `$set` event for this user. To send this event, run the following `curl` command: |
| |
| <div class="tabs"> |
| <div data-tab="REST API" data-lang="json"> |
| ``` |
| $ curl -i -X POST http://localhost:7070/events.json?accessKey=$ACCESS_KEY \ |
| -H "Content-Type: application/json" \ |
| -d '{ |
| "event" : "$set", |
| "entityType" : "user", |
| "entityId" : "u0", |
| "eventTime" : "2014-11-02T09:39:45.618-08:00" |
| }' |
| ``` |
| </div> |
| <div data-tab="Python SDK" data-lang="python"> |
| ```python |
| import predictionio |
| |
| client = predictionio.EventClient( |
| access_key=<ACCESS KEY>, |
| url=<URL OF EVENTSERVER>, |
| threads=5, |
| qsize=500 |
| ) |
| |
| # Create a new user |
| |
| client.create_event( |
| event="$set", |
| entity_type="user", |
| entity_id=<USER_ID> |
| ) |
| ``` |
| </div> |
| |
| <div data-tab="PHP SDK" data-lang="php"> |
| ```php |
| <?php |
| require_once("vendor/autoload.php"); |
| use predictionio\EventClient; |
| |
| $client = new EventClient(<ACCESS KEY>, <URL OF EVENTSERVER>); |
| |
| // Create a new user |
| $client->createEvent(array( |
| 'event' => '$set', |
| 'entityType' => 'user', |
| 'entityId' => <USER ID> |
| )); |
| ?> |
| ``` |
| </div> |
| <div data-tab="Ruby SDK" data-lang="ruby"> |
| ```ruby |
| # Create a client object. |
| client = PredictionIO::EventClient.new(<ACCESS KEY>, <URL OF EVENTSERVER>) |
| |
| # Create a new user |
| client.create_event( |
| '$set', |
| 'user', |
| <USER ID> |
| ) |
| ``` |
| </div> |
| <div data-tab="Java SDK" data-lang="java"> |
| ```java |
| import org.apache.predictionio.Event; |
| import org.apache.predictionio.EventClient; |
| |
| import com.google.common.collect.ImmutableList; |
| |
| EventClient client = new EventClient(<ACCESS KEY>, <URL OF EVENTSERVER>); |
| |
| // Create a new user |
| Event userEvent = new Event() |
| .event("$set") |
| .entityType("user") |
| .entityId(<USER_ID>); |
| client.createEvent(userEvent); |
| ``` |
| </div> |
| </div> |
| |
| |
| When a new item "i0" is created in your app on time `2014-11-02T09:39:45.618-08:00` (current time will be used if eventTime is not specified), you can send a `$set` event for the item. Run the following `curl` command: |
| |
| |
| <div class="tabs"> |
| <div data-tab="REST API" data-lang="json"> |
| ``` |
| $ curl -i -X POST http://localhost:7070/events.json?accessKey=$ACCESS_KEY \ |
| -H "Content-Type: application/json" \ |
| -d '{ |
| "event" : "$set", |
| "entityType" : "item", |
| "entityId" : "i0", |
| "eventTime" : "2014-11-02T09:39:45.618-08:00" |
| }' |
| ``` |
| </div> |
| <div data-tab="Python SDK" data-lang="python"> |
| ```python |
| # Create a new item or set existing item's categories |
| |
| client.create_event( |
| event="$set", |
| entity_type="item", |
| entity_id=<ITEM_ID> |
| ) |
| ``` |
| </div> |
| |
| <div data-tab="PHP SDK" data-lang="php"> |
| ```php |
| <?php |
| // Create a new item or set existing item's categories |
| $client->createEvent(array( |
| 'event' => '$set', |
| 'entityType' => 'item', |
| 'entityId' => <ITEM ID> |
| )); |
| |
| ?> |
| ``` |
| </div> |
| <div data-tab="Ruby SDK" data-lang="ruby"> |
| ```ruby |
| # Create a new item or set existing item's categories |
| client.create_event( |
| '$set', |
| 'item', |
| <ITEM ID> |
| ) |
| |
| ``` |
| </div> |
| <div data-tab="Java SDK" data-lang="java"> |
| ```java |
| // Create a new item or set existing item's categories |
| Event itemEvent = new Event() |
| .event("$set") |
| .entityType("item") |
| .entityId(<ITEM_ID>); |
| client.createEvent(itemEvent) |
| ``` |
| </div> |
| </div> |
| |
| |
| When the user "u0" view item "i0" on time `2014-11-10T12:34:56.123-08:00` (current time will be used if eventTime is not specified), you can send a view event. Run the following `curl` command: |
| |
| |
| <div class="tabs"> |
| <div data-tab="REST API" data-lang="json"> |
| ``` |
| $ curl -i -X POST http://localhost:7070/events.json?accessKey=$ACCESS_KEY \ |
| -H "Content-Type: application/json" \ |
| -d '{ |
| "event" : "view", |
| "entityType" : "user", |
| "entityId" : "u0", |
| "targetEntityType" : "item", |
| "targetEntityId" : "i0", |
| "eventTime" : "2014-11-10T12:34:56.123-08:00" |
| }' |
| ``` |
| </div> |
| <div data-tab="Python SDK" data-lang="python"> |
| ```python |
| # A user views an item |
| |
| client.create_event( |
| event="view", |
| entity_type="user", |
| entity_id=<USER ID>, |
| target_entity_type="item", |
| target_entity_id=<ITEM ID> |
| ) |
| ``` |
| </div> |
| |
| <div data-tab="PHP SDK" data-lang="php"> |
| ```php |
| <?php |
| // A user views an item |
| $client->createEvent(array( |
| 'event' => 'view', |
| 'entityType' => 'user', |
| 'entityId' => <USER ID>, |
| 'targetEntityType' => 'item', |
| 'targetEntityId' => <ITEM ID> |
| )); |
| ?> |
| ``` |
| </div> |
| <div data-tab="Ruby SDK" data-lang="ruby"> |
| ```ruby |
| # A user views an item. |
| client.create_event( |
| 'view', |
| 'user', |
| <USER ID>, { |
| 'targetEntityType' => 'item', |
| 'targetEntityId' => <ITEM ID> |
| } |
| ) |
| ``` |
| </div> |
| <div data-tab="Java SDK" data-lang="java"> |
| ```java |
| // A user views an item |
| Event viewEvent = new Event() |
| .event("view") |
| .entityType("user") |
| .entityId(<USER_ID>) |
| .targetEntityType("item") |
| .targetEntityId(<ITEM_ID>); |
| client.createEvent(viewEvent); |
| ``` |
| </div> |
| </div> |
| |
| <%= partial 'shared/quickstart/query_eventserver' %> |
| |
| ### Import More Sample Data |
| |
| <%= partial 'shared/quickstart/import_sample_data' %> |
| |
| A Python import script `import_eventserver.py` is provided to import sample data. It imports 10 users (with user ID "u1" to "u10") and 50 items (with item ID "i1" to "i50"). Each user then randomly view 10 items. |
| |
| <%= partial 'shared/quickstart/install_python_sdk' %> |
| |
| Make sure you are under the `MyProductRanking` directory. Execute the following to import the data: |
| |
| ``` |
| $ cd MyProductRanking |
| $ python data/import_eventserver.py --access_key $ACCESS_KEY |
| ``` |
| |
| You should see the following output: |
| |
| ``` |
| ... |
| User u10 views item i13 |
| User u10 views item i19 |
| User u10 views item i16 |
| User u10 views item i39 |
| User u10 views item i47 |
| User u10 views item i7 |
| 160 events are imported. |
| ``` |
| |
| <%= partial 'shared/quickstart/query_eventserver_short' %> |
| |
| ## 5. Deploy the Engine as a Service |
| |
| <%= partial 'shared/quickstart/deploy_enginejson', locals: { engine_name: 'MyProductRanking' } %> |
| |
| <%= partial 'shared/quickstart/deploy', locals: { engine_name: 'MyProductRanking' } %> |
| |
| ## 6. Use the Engine |
| |
| Now, You can retrieve predicted results. To rank items with IDs "i1", "i3", "i10", "i2", "i5", "i31", "i9" for user "u2". You send this JSON `{ "user": "u2", "items": ["i1", "i3", "i10", "i2", "i5", "i31", "i9"] }` to the deployed engine and it will return a JSON of the ranked items. Simply send a query by making a HTTP request or through the `EngineClient` of an SDK. |
| |
| With the deployed engine running, open another terminal and run the following `curl` command or use SDK to send the query: |
| |
| <div class="tabs"> |
| <div data-tab="REST API" data-lang="json"> |
| ``` |
| $ curl -H "Content-Type: application/json" \ |
| -d '{ "user": "u2", "items": ["i1", "i3", "i10", "i2", "i5", "i31", "i9"]}' \ |
| http://localhost:8000/queries.json |
| |
| ``` |
| </div> |
| <div data-tab="Python SDK" data-lang="python"> |
| ```python |
| import predictionio |
| engine_client = predictionio.EngineClient(url="http://localhost:8000") |
| print engine_client.send_query({ |
| "user": "u2", |
| "items": ["i1", "i3", "i10", "i2", "i5", "i31", "i9"] |
| }) |
| ``` |
| </div> |
| <div data-tab="PHP SDK" data-lang="php"> |
| ```php |
| <?php |
| require_once("vendor/autoload.php"); |
| use predictionio\EngineClient; |
| |
| $client = new EngineClient('http://localhost:8000'); |
| |
| $response = $client->sendQuery(array( |
| 'user' => 'u2', |
| 'items'=> array('i1', 'i3', 'i10', 'i2', 'i5', 'i31', 'i9') )); |
| print_r($response); |
| |
| ?> |
| ``` |
| </div> |
| <div data-tab="Ruby SDK" data-lang="ruby"> |
| |
| ```ruby |
| # Create client object. |
| client = PredictionIO::EngineClient.new('http://localhost:8000') |
| |
| # Query PredictionIO. |
| response = client.send_query( |
| 'user' => 'u2', |
| 'items' => ['i1', 'i3', 'i10', 'i2', 'i5', 'i31', 'i9']) |
| |
| puts response |
| ``` |
| </div> |
| <div data-tab="Java SDK" data-lang="java"> |
| |
| ```java |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.ImmutableList; |
| import com.google.gson.JsonObject; |
| |
| import org.apache.predictionio.EngineClient; |
| |
| // create client object |
| EngineClient engineClient = new EngineClient("http://localhost:8000"); |
| |
| // query |
| |
| JsonObject response = engineClient.sendQuery(ImmutableMap.<String, Object>of( |
| "user", "u2", |
| "items", ImmutableList.of("i1", "i3", "i10", "i2", "i5", "i31", "i9") |
| )); |
| ``` |
| </div> |
| </div> |
| |
| The following is sample JSON response: |
| |
| ``` |
| { |
| "itemScores":[ |
| {"item":"i5","score":1.0038217983580324}, |
| {"item":"i3","score":0.00598658734782459}, |
| {"item":"i2","score":0.004048103059012265}, |
| {"item":"i9","score":-1.966935819737517E-4}, |
| {"item":"i1","score":-0.0016841195307744916}, |
| {"item":"i31","score":-0.0019770986240634503}, |
| {"item":"i10","score":-0.0031498317618844918} |
| ], |
| "isOriginal":false |
| } |
| ``` |
| |
| *MyProductRanking* is now running. |
| |
| <%= partial 'shared/quickstart/production' %> |
| |
| #### [Next: DASE Components Explained](/templates/productranking/dase/) |