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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +27 -0
  3. data/.gitignore +2 -1
  4. data/.rubocop.yml +21 -0
  5. data/.travis.yml +1 -1
  6. data/README.md +33 -44
  7. data/lateral_recommender.gemspec +8 -10
  8. data/lib/lateral_recommender/version.rb +1 -1
  9. data/lib/lateral_recommender.rb +21 -113
  10. data/spec/fixtures/tapes/add.yml +19 -15
  11. data/spec/fixtures/tapes/invalid_key.yml +21 -19
  12. data/spec/fixtures/tapes/recommend_by_id.yml +40 -0
  13. data/spec/fixtures/tapes/recommend_by_id_arxiv.yml +201 -0
  14. data/spec/fixtures/tapes/recommend_by_id_news.yml +379 -0
  15. data/spec/fixtures/tapes/recommend_by_id_sec.yml +12392 -0
  16. data/spec/fixtures/tapes/recommend_by_id_wikipedia.yml +125 -0
  17. data/spec/fixtures/tapes/recommend_by_text.yml +40 -0
  18. data/spec/fixtures/tapes/recommend_by_text_arxiv.yml +236 -0
  19. data/spec/fixtures/tapes/recommend_by_text_news.yml +294 -0
  20. data/spec/fixtures/tapes/recommend_by_text_pubmed.yml +251 -0
  21. data/spec/fixtures/tapes/recommend_by_text_sec.yml +11469 -0
  22. data/spec/fixtures/tapes/recommend_by_text_wikipedia.yml +118 -0
  23. data/spec/lateral_recommender_spec.rb +67 -101
  24. metadata +89 -78
  25. data/spec/fixtures/tapes/add_user.yml +0 -56
  26. data/spec/fixtures/tapes/add_user_document.yml +0 -879
  27. data/spec/fixtures/tapes/near_id.yml +0 -47
  28. data/spec/fixtures/tapes/near_id_arxiv.yml +0 -68
  29. data/spec/fixtures/tapes/near_text.yml +0 -47
  30. data/spec/fixtures/tapes/near_text_arxiv.yml +0 -91
  31. data/spec/fixtures/tapes/near_text_movies.yml +0 -1262
  32. data/spec/fixtures/tapes/near_text_news.yml +0 -400
  33. data/spec/fixtures/tapes/near_text_pubmed.yml +0 -70
  34. data/spec/fixtures/tapes/near_text_wikipedia.yml +0 -55
  35. data/spec/fixtures/tapes/near_user.yml +0 -56
  36. data/spec/fixtures/tapes/near_user_arxiv.yml +0 -152
  37. data/spec/fixtures/tapes/near_user_movies.yml +0 -1262
  38. data/spec/fixtures/tapes/near_user_news.yml +0 -400
  39. data/spec/fixtures/tapes/near_user_pubmed.yml +0 -116
  40. 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: 30f817bfa2c49f5b662223f53679499fef6f4343
4
- data.tar.gz: 4882d70fdf91115eb50ba45dc766e781853f2dac
3
+ metadata.gz: 6ef7a043d9d6945e21428e2afe94f637d41d9ba4
4
+ data.tar.gz: c527e7dca6487d9d098cf7b90851ad0e201ee5ad
5
5
  SHA512:
6
- metadata.gz: eaa4b721f15177afae07bd0e651b551f97e55766b25cc5a315ac9082897298d58e83a1d2ff6d952517e18c3a68350670146e37da85035e93d43e808d0e65387b
7
- data.tar.gz: 2734b5bd4b4e992d2ca9dba15d83e92ee8ce7e8362b71a7ea7730d83ef88eaba5fa7a70aa5848506fbd792eb720476a9ea939be9de59a021d9d22704117b60eb
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
@@ -20,4 +20,5 @@ tmp
20
20
  *.o
21
21
  *.a
22
22
  mkmf.log
23
- spec/env_vars.rb
23
+ spec/env_vars.rb
24
+ vendor/
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: Ri31ozxBLZ9/lzvejfgdtM9LVFdB7kKITRwCSZ9KvSKocy+msPUxND9t8G9cqr6fKU0yzSrYcGdBYP8S3SXOUI+a9Ev5UeQPU8lcZWIg9Bqe4RaIif/anKeCyamoCunReHQ9sxziVSMfg+yn0yoNS8epUA9BbBpqZDeeVMSW9qY=
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/api). It currently supports `add` and `near_text` from the [Recommender API](https://developers.lateral.io/docs/services/546b2cc23705a70f4cd2766d/operations/546b2e053705a70f4cd2766e) and the complete (experimental) [Personalisation API](https://developers.lateral.io/docs/services/54b7f0923705a712c0f43836/operations/54b7f3753705a712c0f4383f). Over time the missing API methods will be added and this will become a fully featured wrapper around the Lateral API.
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
- Until the gem is more complete, it will not be available on rubygems.org. So to add it, add this line to your application's Gemfile:
9
+ Add this line to your application's Gemfile:
12
10
 
13
- gem 'lateral_recommender', github: 'lateral/recommender-gem'
11
+ ```ruby
12
+ gem 'lateral_recommender'
13
+ ```
14
14
 
15
15
  And then execute:
16
16
 
17
- $ bundle install
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, [sign up here](https://developers.lateral.io/signup/) then visit your [profile](https://developers.lateral.io/developer) and click 'Show' next to where it says `Primary key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX`.
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
- To get recommendations for some text, use `near_text`:
43
+ #### Recommend by text
44
+
45
+ To get recommendations for some text, use `recommend_by_text`:
44
46
 
45
47
  ```ruby
46
- api.near_text 'document text'
48
+ api.recommend_by_text 'document text'
47
49
  ```
48
50
 
49
- To get recommendations for a document that's in the API, use `near_id`:
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.near_id 'document_id'
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
- #### Querying our pre-populated data
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-filled data sets:
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
- * **[Movies](https://www.freebase.com/film/film?instances)** (experimental) - Movies listed on [Freebase](https://www.freebase.com/) with plots from [Wikipedia](https://en.wikipedia.org)
62
- * **News** (experimental) - News from multiple outlets updated every 15 minutes
63
- * **[arXiv](http://arxiv.org/)** - Academic papers in Physics, Mathematics, Computer Science, Quantitative Biology, Quantitative Finance and Statistics
64
- * **[PubMed](http://www.ncbi.nlm.nih.gov/pubmed)** - Medical journals
65
- * **[Wikipedia](https://en.wikipedia.org)** - General knowledge
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, simply initialize `LateralRecommender` with a second argument containing the corpus:
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 `movies`, `news`, `arxiv`, `pubmed` or `wikipedia`. We plan to add more in the near future.
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.add_user 'user_id'
79
+ api.recommend_by_text 'document text'
91
80
  ```
92
81
 
93
- To add a document to that user:
82
+ Or with a document ID:
94
83
 
95
84
  ```ruby
96
- api.add_user_document 'user_id', 'document_id', 'document text'
85
+ api.recommend_by_id 'arxiv-http://arxiv.org/abs/1403.2165'
97
86
  ```
98
87
 
99
- You can do this as many times as you want to build a more complete picture of the user. Then, to query for recommendations for that user:
88
+ Note: For the SEC data, you need to set a collections array:
100
89
 
101
90
  ```ruby
102
- api.near_user 'user_id'
91
+ api.recommend_by_text 'document text', collections: '["item1a"]'
103
92
  ```
104
93
 
105
- The response will be the same format as a `near_text`.
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.
@@ -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 'bundler', '~> 1.6'
21
- spec.add_development_dependency 'rake'
22
- spec.add_development_dependency 'rspec'
23
- spec.add_development_dependency 'vcr'
24
- spec.add_development_dependency 'webmock'
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 'httpclient'
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
@@ -1,3 +1,3 @@
1
1
  module LateralRecommender
2
- VERSION = "0.0.2"
2
+ VERSION = '0.0.3'
3
3
  end
@@ -1,17 +1,18 @@
1
1
  require 'lateral_recommender/version'
2
- require 'httpclient'
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] corpora The corpora to recommend from e.g. movies, news, wikipedia, arxiv or pubmed
10
- def initialize(key, corpora = 'recommender')
11
- @corpora = %w(movies news wikipedia arxiv pubmed).include?(corpora) ? "collections/#{corpora}" : corpora
12
- @uri = 'https://api.lateral.io/'
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 "#{@corpora}/add", params.stringify_keys
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 near_text(text, opts = {})
36
- post "#{@corpora}/recommend", { text: text }.merge(opts)
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] text The ID of the document to get recommendations for.
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 near_user(id, opts = {})
58
- if @corpora != 'recommender'
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.status != 200 && request.status != 201
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
- begin
161
- message = JSON.parse(request.body)['message']
162
- rescue
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
- "#{@uri}#{path}/?subscription-key=#{@key}"
79
+ "#{@endpoint}#{path}/?subscription-key=#{@key}"
171
80
  end
172
81
 
173
82
  def post(path, params)
174
- req @client.post url(path), params.stringify_keys
83
+ req HTTParty.post url(path), body: params
175
84
  end
176
85
 
177
86
  def get(path, params)
178
- req @client.get url(path), params.stringify_keys
87
+ req HTTParty.get url(path), body: params
179
88
  end
180
89
  end
181
90
  end
182
-