blob: 1e299ae06b808c15c1bf9b55726adc9a47ac8b25 [file] [log] [blame]
---
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/)