lateral_recommender 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +27 -0
- data/.gitignore +2 -1
- data/.rubocop.yml +21 -0
- data/.travis.yml +1 -1
- data/README.md +33 -44
- data/lateral_recommender.gemspec +8 -10
- data/lib/lateral_recommender/version.rb +1 -1
- data/lib/lateral_recommender.rb +21 -113
- data/spec/fixtures/tapes/add.yml +19 -15
- data/spec/fixtures/tapes/invalid_key.yml +21 -19
- data/spec/fixtures/tapes/recommend_by_id.yml +40 -0
- data/spec/fixtures/tapes/recommend_by_id_arxiv.yml +201 -0
- data/spec/fixtures/tapes/recommend_by_id_news.yml +379 -0
- data/spec/fixtures/tapes/recommend_by_id_sec.yml +12392 -0
- data/spec/fixtures/tapes/recommend_by_id_wikipedia.yml +125 -0
- data/spec/fixtures/tapes/recommend_by_text.yml +40 -0
- data/spec/fixtures/tapes/recommend_by_text_arxiv.yml +236 -0
- data/spec/fixtures/tapes/recommend_by_text_news.yml +294 -0
- data/spec/fixtures/tapes/recommend_by_text_pubmed.yml +251 -0
- data/spec/fixtures/tapes/recommend_by_text_sec.yml +11469 -0
- data/spec/fixtures/tapes/recommend_by_text_wikipedia.yml +118 -0
- data/spec/lateral_recommender_spec.rb +67 -101
- metadata +89 -78
- data/spec/fixtures/tapes/add_user.yml +0 -56
- data/spec/fixtures/tapes/add_user_document.yml +0 -879
- data/spec/fixtures/tapes/near_id.yml +0 -47
- data/spec/fixtures/tapes/near_id_arxiv.yml +0 -68
- data/spec/fixtures/tapes/near_text.yml +0 -47
- data/spec/fixtures/tapes/near_text_arxiv.yml +0 -91
- data/spec/fixtures/tapes/near_text_movies.yml +0 -1262
- data/spec/fixtures/tapes/near_text_news.yml +0 -400
- data/spec/fixtures/tapes/near_text_pubmed.yml +0 -70
- data/spec/fixtures/tapes/near_text_wikipedia.yml +0 -55
- data/spec/fixtures/tapes/near_user.yml +0 -56
- data/spec/fixtures/tapes/near_user_arxiv.yml +0 -152
- data/spec/fixtures/tapes/near_user_movies.yml +0 -1262
- data/spec/fixtures/tapes/near_user_news.yml +0 -400
- data/spec/fixtures/tapes/near_user_pubmed.yml +0 -116
- data/spec/fixtures/tapes/near_user_wikipedia.yml +0 -88
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ef7a043d9d6945e21428e2afe94f637d41d9ba4
|
4
|
+
data.tar.gz: c527e7dca6487d9d098cf7b90851ad0e201ee5ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f64c85dd58161f6b912b8f2f5556c8b756341d014448bfe9b4433c591ea9d33c3f15d398594e5705108631bd1ca309554449922862ea2bdc0e733a2691e4a16
|
7
|
+
data.tar.gz: 8409c4294b9b381ea9b8c8f25ae0484633dab2134fbc80a8940369ca72cde6e960500a6d79e904519c3a618ca78312654816dd974c4ca10a5a544aa810bcd2d4
|
data/.editorconfig
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# EditorConfig helps developers define and maintain consistent
|
2
|
+
# coding styles between different editors and IDEs
|
3
|
+
# editorconfig.org
|
4
|
+
|
5
|
+
root = true
|
6
|
+
|
7
|
+
|
8
|
+
[*]
|
9
|
+
|
10
|
+
# Change these settings to your own preference
|
11
|
+
indent_style = spaces
|
12
|
+
indent_size = 2
|
13
|
+
|
14
|
+
# We recommend you to keep these unchanged
|
15
|
+
end_of_line = lf
|
16
|
+
charset = utf-8
|
17
|
+
trim_trailing_whitespace = true
|
18
|
+
insert_final_newline = true
|
19
|
+
|
20
|
+
[*.md]
|
21
|
+
trim_trailing_whitespace = false
|
22
|
+
|
23
|
+
[*.config]
|
24
|
+
indent_style = space
|
25
|
+
|
26
|
+
[*.yml]
|
27
|
+
indent_style = space
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
AllCops:
|
2
|
+
Include:
|
3
|
+
- Rakefile
|
4
|
+
- config.ru
|
5
|
+
Exclude:
|
6
|
+
- db/**/*
|
7
|
+
- vendor/**/*
|
8
|
+
- bin/**/*
|
9
|
+
- lib/rack/*
|
10
|
+
|
11
|
+
LineLength:
|
12
|
+
Max: 100
|
13
|
+
|
14
|
+
RescueModifier:
|
15
|
+
Enabled: false
|
16
|
+
|
17
|
+
AndOr:
|
18
|
+
Enabled: false
|
19
|
+
|
20
|
+
ClassAndModuleChildren:
|
21
|
+
Enabled: false
|
data/.travis.yml
CHANGED
@@ -12,4 +12,4 @@ rvm:
|
|
12
12
|
- jruby-19mode
|
13
13
|
env:
|
14
14
|
global:
|
15
|
-
- secure:
|
15
|
+
- secure: "G2F3imFzu0RK7aRKe5UMBkjpmKxRWPfCluBQ0sHIzxcV7/haWuIgs2hh6/lA/z7HtcAvq0yPPJIzcuCenvYBgui19/TT4WeteKKtopwPwGElkXar5ch5PVee96kcwCTeQP/UNQZcdZW9AZjog2FaqKaxiKB9P+cVpkRMSRHBDjw="
|
data/README.md
CHANGED
@@ -2,27 +2,25 @@
|
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.org/lateral/recommender-gem.svg?branch=master)](https://travis-ci.org/lateral/recommender-gem)
|
4
4
|
|
5
|
-
This is a Ruby wrapper around the [Lateral API](https://lateral.io/
|
6
|
-
|
7
|
-
*For the full API specification please see the [documentation here](https://developers.lateral.io/docs/services/).*
|
5
|
+
This is a Ruby wrapper around the [Lateral](https://lateral.io/) [Conceptual text-matching API](https://lateral.io/docs/text-matching). At the moment it only supports [/add](https://lateral.io/docs/text-matching/api-reference#add-document-post), [/recommend-by-text](https://lateral.io/docs/text-matching/api-reference#recommend-by-text-post), [/recommend-by-id](https://lateral.io/docs/text-matching/api-reference#recommend-by-id-post) and our [pre-populated recommenders](https://lateral.io/docs/text-matching/pre-populated-recommenders). You can find the full API reference [here](https://lateral.io/docs/text-matching/api-reference).
|
8
6
|
|
9
7
|
## Installation
|
10
8
|
|
11
|
-
|
9
|
+
Add this line to your application's Gemfile:
|
12
10
|
|
13
|
-
|
11
|
+
```ruby
|
12
|
+
gem 'lateral_recommender'
|
13
|
+
```
|
14
14
|
|
15
15
|
And then execute:
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
Or you can [install it manually](https://stackoverflow.com/questions/2577346/how-to-install-gem-from-github-source).
|
17
|
+
$ bundle install
|
20
18
|
|
21
19
|
## Usage
|
22
20
|
|
23
21
|
### Get an API key
|
24
22
|
|
25
|
-
An API key is required in order to use our API. To do this
|
23
|
+
An API key is required in order to use our API. To do this go to our [docs page](https://lateral.io/docs) and click the 'Get Access' button in the top right. Choose the 'Conceptual text-matcher' API and you'll get emailed details of how to get your key.
|
26
24
|
|
27
25
|
### Use the API
|
28
26
|
|
@@ -32,6 +30,8 @@ Initialize `LateralRecommender` with your API key by running:
|
|
32
30
|
api = LateralRecommender::API.new YOUR_API_KEY
|
33
31
|
```
|
34
32
|
|
33
|
+
#### Add a document
|
34
|
+
|
35
35
|
To add a document to the API call:
|
36
36
|
|
37
37
|
```ruby
|
@@ -40,69 +40,58 @@ api.add document_id: 'document_id', text: 'document text'
|
|
40
40
|
|
41
41
|
Please be aware that if you don't send enough meaningful text the API will return an error. So please ensure there is at least 100 or so words in the document you're adding.
|
42
42
|
|
43
|
-
|
43
|
+
#### Recommend by text
|
44
|
+
|
45
|
+
To get recommendations for some text, use `recommend_by_text`:
|
44
46
|
|
45
47
|
```ruby
|
46
|
-
api.
|
48
|
+
api.recommend_by_text 'document text'
|
47
49
|
```
|
48
50
|
|
49
|
-
|
51
|
+
#### Recommend by ID
|
52
|
+
|
53
|
+
To get recommendations for a document that's in the API, use `recommend_by_id`:
|
50
54
|
|
51
55
|
```ruby
|
52
|
-
api.
|
56
|
+
api.recommend_by_id 'document_id'
|
53
57
|
```
|
54
|
-
|
55
58
|
This returns an array of Hashes containing a `document_id` and `distance`.
|
56
59
|
|
57
|
-
####
|
60
|
+
#### Pre-populated recommenders
|
58
61
|
|
59
|
-
If you don't want to insert your own documents to the API, you can query one of our pre-
|
62
|
+
If you don't want to insert your own documents to the API, you can query one of our pre-populated recommenders:
|
60
63
|
|
61
|
-
* **[
|
62
|
-
* **News
|
63
|
-
* **[
|
64
|
-
* **[
|
65
|
-
* **[Wikipedia](https://
|
64
|
+
* **[arXiv](https://lateral.io/docs/text-matching/pre-populated-recommenders#arxiv)** - 1M+ academic papers in Physics, Mathematics and Computer Science (updated daily)
|
65
|
+
* **[News](https://lateral.io/docs/text-matching/pre-populated-recommenders#news)** - 250,000+ curated news articles (updated every 15mins)
|
66
|
+
* **[PubMed](https://lateral.io/docs/text-matching/pre-populated-recommenders#pubmed)** - Medical journals
|
67
|
+
* **[SEC Data](https://lateral.io/docs/text-matching/pre-populated-recommenders#sec-data)** - 6,000+ yearly financial reports / 10-K filings (from 2014)
|
68
|
+
* **[Wikipedia](https://lateral.io/docs/text-matching/pre-populated-recommenders#wikipedia)** - 463,000 Wikipedia pages (which had 20+ page views in 2013)
|
66
69
|
|
67
|
-
To use these,
|
70
|
+
To use one of these, initialize `LateralRecommender` with a second argument containing the corpus:
|
68
71
|
|
69
72
|
```ruby
|
70
73
|
api = LateralRecommender::API.new YOUR_API_KEY, 'news'
|
71
74
|
```
|
72
75
|
|
73
|
-
The available values are `
|
74
|
-
|
75
|
-
Now you can query the API using `near_text` or `near_user` without the need for populating the API with your own content:
|
76
|
-
|
77
|
-
```ruby
|
78
|
-
api.near_text 'document text'
|
79
|
-
```
|
80
|
-
|
81
|
-
#### Managing users
|
82
|
-
|
83
|
-
A feature of the API is to be able to add a representation of a user. The user is able to have many documents and when querying the API for recommendations you can specify the user and each of these documents will be used to get recommendations for that user.
|
84
|
-
|
85
|
-
*Note: This is an experimental feature of the API*
|
86
|
-
|
87
|
-
To add a user:
|
76
|
+
The available values are `arxiv`, `news`, `pubmed`, `sec` or `wikipedia`. These allow you to query the recommender using `recommend_by_text` or `recommend_by_id` without the need for adding your own documents. By text:
|
88
77
|
|
89
78
|
```ruby
|
90
|
-
api.
|
79
|
+
api.recommend_by_text 'document text'
|
91
80
|
```
|
92
81
|
|
93
|
-
|
82
|
+
Or with a document ID:
|
94
83
|
|
95
84
|
```ruby
|
96
|
-
api.
|
85
|
+
api.recommend_by_id 'arxiv-http://arxiv.org/abs/1403.2165'
|
97
86
|
```
|
98
87
|
|
99
|
-
|
88
|
+
Note: For the SEC data, you need to set a collections array:
|
100
89
|
|
101
90
|
```ruby
|
102
|
-
api.
|
91
|
+
api.recommend_by_text 'document text', collections: '["item1a"]'
|
103
92
|
```
|
104
93
|
|
105
|
-
|
94
|
+
Read the [Pre-populated-recommenders documentation](https://lateral.io/docs/text-matching/pre-populated-recommenders#top) for more.
|
106
95
|
|
107
96
|
## Contributing
|
108
97
|
|
@@ -115,4 +104,4 @@ The response will be the same format as a `near_text`.
|
|
115
104
|
|
116
105
|
### Testing
|
117
106
|
|
118
|
-
To test the gem, run `bundle exec rspec`. Note: your API key must be un-used.
|
107
|
+
To test the gem, run `bundle exec rspec`. Note: your API key must be un-used.
|
data/lateral_recommender.gemspec
CHANGED
@@ -16,15 +16,13 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
17
|
spec.require_paths = ['lib']
|
18
18
|
|
19
|
-
spec.add_development_dependency 'awesome_print'
|
20
|
-
spec.add_development_dependency '
|
21
|
-
spec.add_development_dependency '
|
22
|
-
spec.add_development_dependency '
|
23
|
-
spec.add_development_dependency '
|
24
|
-
spec.add_development_dependency '
|
25
|
-
spec.add_development_dependency 'yard'
|
19
|
+
spec.add_development_dependency 'awesome_print', '~> 1.6', '>= 1.6.1'
|
20
|
+
spec.add_development_dependency 'rake', '~> 10.4', '>= 10.4.2'
|
21
|
+
spec.add_development_dependency 'rspec', '~> 3.2', '>= 3.2.0'
|
22
|
+
spec.add_development_dependency 'vcr', '~> 2.9', '>= 2.9.3'
|
23
|
+
spec.add_development_dependency 'webmock', '~> 1.21', '>= 1.21.0'
|
24
|
+
spec.add_development_dependency 'yard', '~> 0.8', '>= 0.8.7.6'
|
26
25
|
|
27
|
-
spec.add_runtime_dependency '
|
28
|
-
spec.add_runtime_dependency 'json'
|
29
|
-
spec.add_runtime_dependency 'activesupport'
|
26
|
+
spec.add_runtime_dependency 'httparty', '~> 0.13', '>= 0.13.4'
|
27
|
+
spec.add_runtime_dependency 'json', '~> 1.8', '>= 1.8.2'
|
30
28
|
end
|
data/lib/lateral_recommender.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
require 'lateral_recommender/version'
|
2
|
-
require '
|
3
|
-
require 'active_support/core_ext/hash'
|
2
|
+
require 'httparty'
|
4
3
|
require 'json'
|
5
4
|
|
6
5
|
module LateralRecommender
|
7
6
|
class API
|
7
|
+
EXTERNAL_CORPORA = %w(arxiv news pubmed sec wikipedia)
|
8
|
+
|
8
9
|
# @param [String] key The Lateral API key
|
9
|
-
# @param [String]
|
10
|
-
def initialize(key,
|
11
|
-
|
12
|
-
@
|
10
|
+
# @param [String] corpus The corpora to recommend from e.g. arxiv, sec, pubmed, wikipedia, news
|
11
|
+
def initialize(key, corpus = 'recommender')
|
12
|
+
corpus = EXTERNAL_CORPORA.include?(corpus) ? corpus : 'recommender'
|
13
|
+
@endpoint = "https://#{corpus}-api.lateral.io/"
|
13
14
|
@key = key
|
14
|
-
@client = HTTPClient.new
|
15
|
+
# @client = HTTPClient.new
|
15
16
|
end
|
16
17
|
|
17
18
|
# Add a document to the recommender
|
@@ -22,7 +23,7 @@ module LateralRecommender
|
|
22
23
|
# @option params [String] :meta A JSON object containing any metadata
|
23
24
|
# @return [Hash] the document object that was added.
|
24
25
|
def add(params)
|
25
|
-
post
|
26
|
+
post 'add', params
|
26
27
|
end
|
27
28
|
|
28
29
|
# Get recommendations for the provided text
|
@@ -32,107 +33,19 @@ module LateralRecommender
|
|
32
33
|
# @option opts [Integer] :results (20) How many results to return
|
33
34
|
# @option opts [Array] :select_from An array of IDs to return results from
|
34
35
|
# @return [Array] An array of Hashes containing the recommendations
|
35
|
-
def
|
36
|
-
post
|
36
|
+
def recommend_by_text(text, opts = {})
|
37
|
+
post 'recommend-by-text', { text: text }.merge(opts)
|
37
38
|
end
|
38
39
|
|
39
40
|
# Get recommendations for the provided id
|
40
41
|
#
|
41
|
-
# @param [String]
|
42
|
-
# @param [Hash] opts Additional options for the request.
|
43
|
-
# @option opts [Integer] :results (20) How many results to return
|
44
|
-
# @option opts [Array] :select_from An array of IDs to return results from
|
45
|
-
# @return [Array] An array of Hashes containing the recommendations
|
46
|
-
def near_id(id, opts = {})
|
47
|
-
post "#{@corpora}/recommend", { document_id: id }.merge(opts)
|
48
|
-
end
|
49
|
-
|
50
|
-
# Get recommendations for the provided text
|
51
|
-
#
|
52
|
-
# @param [String] id The ID of the user to return recommendations for
|
42
|
+
# @param [String] id The ID of the document to get recommendations for.
|
53
43
|
# @param [Hash] opts Additional options for the request.
|
54
44
|
# @option opts [Integer] :results (20) How many results to return
|
55
45
|
# @option opts [Array] :select_from An array of IDs to return results from
|
56
46
|
# @return [Array] An array of Hashes containing the recommendations
|
57
|
-
def
|
58
|
-
|
59
|
-
opts = opts.merge corpus: @corpora.gsub('collections/', '')
|
60
|
-
end
|
61
|
-
post 'personalisation/recommend', { user_id: id }.merge(opts)
|
62
|
-
end
|
63
|
-
|
64
|
-
# Get all users
|
65
|
-
#
|
66
|
-
# @return [Array] An array of all user Hashes
|
67
|
-
def users
|
68
|
-
get 'personalisation/users'
|
69
|
-
end
|
70
|
-
|
71
|
-
# Get one user
|
72
|
-
#
|
73
|
-
# @param [String] id The ID of the user to return
|
74
|
-
# @return [Hash] A user Hash
|
75
|
-
def get_user(id)
|
76
|
-
get 'personalisation/users', id: id
|
77
|
-
end
|
78
|
-
|
79
|
-
# Add a user
|
80
|
-
#
|
81
|
-
# @param [String] id The ID of the user to add
|
82
|
-
# @return [Hash] The user Hash
|
83
|
-
def add_user(id)
|
84
|
-
post 'personalisation/users', id: id
|
85
|
-
end
|
86
|
-
|
87
|
-
# Delete a user
|
88
|
-
#
|
89
|
-
# @param [String] id The ID of the user to add
|
90
|
-
# @return [Hash] The user Hash
|
91
|
-
def delete_user(id)
|
92
|
-
delete 'personalisation/users', id: id
|
93
|
-
end
|
94
|
-
|
95
|
-
# Get all user documents
|
96
|
-
#
|
97
|
-
# @return [Array] An array of all document Hashes
|
98
|
-
def user_documents
|
99
|
-
get 'personalisation/documents'
|
100
|
-
end
|
101
|
-
|
102
|
-
# Get all user documents for a specified user
|
103
|
-
#
|
104
|
-
# @param [String] user_id The ID of the user
|
105
|
-
# @return [Array] An array of document Hashes that belong to the user
|
106
|
-
def user_documents(user_id)
|
107
|
-
get 'personalisation/documents/by-user', user_id: user_id
|
108
|
-
end
|
109
|
-
|
110
|
-
# Get one document that belongs to a specified user
|
111
|
-
#
|
112
|
-
# @param [String] user_id The ID of the user
|
113
|
-
# @param [String] document_id The ID of the document
|
114
|
-
# @return [Hash] An document Hash
|
115
|
-
def user_document(user_id, document_id)
|
116
|
-
get 'personalisation/documents/by-id', user_id: user_id, id: document_id
|
117
|
-
end
|
118
|
-
|
119
|
-
# Add a document to a user
|
120
|
-
#
|
121
|
-
# @param [String] user_id The ID of the user
|
122
|
-
# @param [String] document_id The ID of the document
|
123
|
-
# @param [String] body The contents of the document
|
124
|
-
# @return [Hash] The documents Hash
|
125
|
-
def add_user_document(user_id, document_id, body, opts = {})
|
126
|
-
post 'personalisation/documents', { user_id: user_id, id: document_id, body: body }.merge(opts)
|
127
|
-
end
|
128
|
-
|
129
|
-
# Delete a users document
|
130
|
-
#
|
131
|
-
# @param [String] user_id The ID of the user
|
132
|
-
# @param [String] document_id The ID of the document
|
133
|
-
# @return [Hash] The documents Hash
|
134
|
-
def delete_user_document(user_id, document_id)
|
135
|
-
delete 'personalisation/documents', user_id: user_id, id: document_id
|
47
|
+
def recommend_by_id(id, opts = {})
|
48
|
+
post 'recommend-by-id', { document_id: id }.merge(opts)
|
136
49
|
end
|
137
50
|
|
138
51
|
# Takes two result arrays and using the specified key merges the two
|
@@ -152,31 +65,26 @@ module LateralRecommender
|
|
152
65
|
private
|
153
66
|
|
154
67
|
def req(request)
|
155
|
-
return { error: error(request) } if request.
|
68
|
+
return { error: error(request) } if request.code != 200 && request.code != 201
|
156
69
|
JSON.parse(request.body)
|
157
70
|
end
|
158
71
|
|
159
72
|
def error(request)
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
message = request.header.reason_phrase
|
164
|
-
end
|
165
|
-
return { status_code: request.status } unless message
|
166
|
-
{ status_code: request.status, message: message }
|
73
|
+
{ status_code: request.code, message: JSON.parse(request.body)['message'] }
|
74
|
+
rescue JSON::ParserError
|
75
|
+
{ status_code: request.code }
|
167
76
|
end
|
168
77
|
|
169
78
|
def url(path)
|
170
|
-
"#{@
|
79
|
+
"#{@endpoint}#{path}/?subscription-key=#{@key}"
|
171
80
|
end
|
172
81
|
|
173
82
|
def post(path, params)
|
174
|
-
req
|
83
|
+
req HTTParty.post url(path), body: params
|
175
84
|
end
|
176
85
|
|
177
86
|
def get(path, params)
|
178
|
-
req
|
87
|
+
req HTTParty.get url(path), body: params
|
179
88
|
end
|
180
89
|
end
|
181
90
|
end
|
182
|
-
|