Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

# Temp files
.#*
rewards
hits
bandit-server
1 change: 0 additions & 1 deletion .godir

This file was deleted.

25 changes: 0 additions & 25 deletions Dockerfile

This file was deleted.

35 changes: 0 additions & 35 deletions Godeps/Godeps.json

This file was deleted.

5 changes: 0 additions & 5 deletions Godeps/Readme

This file was deleted.

21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

27 changes: 0 additions & 27 deletions Makefile

This file was deleted.

1 change: 0 additions & 1 deletion Procfile

This file was deleted.

136 changes: 97 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,79 +1,137 @@
# Bandit-server

Bandit-server is a [Multi-Armed Bandit](http://en.wikipedia.org/wiki/Multi-armed_bandit) api server which needs no configuration neither persistente store.
Bandit-server is a [Multi-Armed Bandit](http://en.wikipedia.org/wiki/Multi-armed_bandit) api server which needs no configuration

## Multi-armed what?!
## Getting Started

A multi-armed bandit is essentially an online alternative to classical A/B testing. Whereas A/B testing is generally split into extended phases of execution and analysis, Bandit algorithms continually adjust to user feedback and optimize between experimental states. Bandits typically require very little curation and can in fact be left running indefinitely if need be.
1. Install bandit-server. ``go get github.com/recoilme/bandit-server``
2. Run ```bandit-server --port=3000 --debug=true```

The curious sounding name is drawn from the "one-armed bandit", an colloquialism for casino slot machines. Bandit algorithms can be thought of along similar lines as a eager slot player: if one were to play many slot machines continuously over many thousands of attempts, one would eventually be able to determine which machines were hotter than others. A multi-armed bandit is merely an algorithm that performs exactly this determination, using your user's interaction as its "arm pulls". Extracting winning patterns becomes a fluid part of interacting with the application.
## Routers

John Myles White has an awesome treatise on Bandit implementations in his book [Bandit Algorithms for Website Optimization](http://shop.oreilly.com/product/0636920027393.do).
```
GET / --> main.ok (3 handlers) - for check status
GET /stats/:group/:count --> main.stats (3 handlers) - for get stats by count arms
POST /stats/:group/:count --> main.stats (3 handlers) - for get stats by arms
POST /write/:param/:group --> main.write (3 handlers) - for write hits & rewards
```

## Getting Started
## Hits

Hits - это количество показов объявлений. Для каждого объявления передаются:

- название объявления, строка, это рука многорукого бандита (arm)
- количество, (cnt) - целое число

Запрос идет на url http://localhost:3000/write/hits/domainid42

где domainid42 - это группа, по которой считается статистика. В нашем случае domainId. Но может быть любая строка.

Метод - POST


Статистика передается в виде json массива. Заголовок: Content-Type: application/json


Пример запроса:
```
curl -X POST --data '[{"arm":"ads 1","cnt":1},{"arm":"ads 2","cnt":1}]' -H "Content-Type: application/json" http://localhost:3000/write/hits/domainid42
```

На этот запрос сервер ответит:

1. Install bandit-server. ``go get github.com/peleteiro/bandit-server``
2. Run ```bandit-server --port=3000```
3. Play ``curl http://localhost:3000/ucb1?downloadButtonColor=black,white,blue\&downloadButtonText=default,now``
4. Reward ``curl -X PUT --data "downloadButtonColor=blue" http://localhost:3000/ucb1``

## Determining what to test
HTTP/1.1 200 OK

The first task at hand requires a little planning. What are some of the things in your app you've always been curious about changing, but never had empirical data to back up potential modifications? Bandits are best suited to cases where changes can be "slipped in" without the user noticing, but since the state assigned to a user will be persisted to their client, you can also change things like UI.

For our example case, we'll be changing the text and color of a download button in our website to see if either change increases user interaction with the feature. We'll be representing these states as two separate experiments (so a user will get separate assignments for color and text).
Текст ответа:
ok

## Experiments Setup
Пример "кривого", неправильного запроса:

You keep experiments on your app, there's no experiments setup on the bandit-server. When you call the api you give a set of arms for every experiment and the server uses this configuration. If you call the api changing the configuration it will adapt the data for the new configuration.
```
curl -v -X POST --data '[{"arm":"ads 1","cnt":1},{"arm":"ads 2","cnt":"2"]' -H "Content-Type: application/json" http://localhost:3000/write/hits/domainid42
```
Ответ с ошибкой:
```
HTTP/1.1 422 Unprocessable Entity
Текст ответа:
{"error":"invalid character '\"' after array element"}
```
422 - это код ошибки.

In your application you call the api ``http://server/ucb1?downloadButtonColor=black,white,blue`` to get the arm you need to show your user and the server will configure itself and the algorithms considering this configuration. If you give up testing "blue" arm, then your app calls ``http://server/ucb1?downloadButtonColor=black,white`` and, again, bandit-server will reconfigure and not losing any statistical data.
## Rewards

## Storage
Rewards - это награда за клик по объявлению.
Формат точно такой же. Единственное отличие - в url вместо hits передается rewards

By default bandit-server uses global memory to storage statistical data. It's the best option, even for multiple instances, if your bandit-server stays alive and you have enough hits. If your server goes down or you add a new server on your cluster, Multi-Armed Bandit algorithms adjust the result fast enough.
Пример:
```
curl -X POST --data '[{"arm":"ads 2","cnt":1}]' -H "Content-Type: application/json" http://localhost:3000/write/rewards/domainid42
```

If you need to persist, you can use memcached: ``bandit-server --memcached=host:port``
## Stats

## Writing your own client considerations
Статистика запрашивается в следуещем формате:

Bandit-server keeps no user state. But usually you want to keep the experiment's choices for a while. You don't want your user to see a different button color every reload.
curl -X GET http://localhost:3000/stats/domainid42/2

It's your client job to keep a local cache on your app for the user session. I personally use bandit-server with one-page apps or native mobile apps, and it's really easy to keep this cache using localstore or filesystem. It should be easy to keep cache in traditional web app using sessions as well.
где domainid42 - это наша группа, 2 - Это количество рук, которые надо вернуть

If you're going to write a client for bandit-server, read the [angular-bandit-client](https://github.com/peleteiro/angular-bandit-client) code and how it handles cache and failure.
Пример ответа:

# Algorithms
```
[{"arm":"var2","hit":1,"rew":0,"score":1.9727697022487511},{"arm":"ads 2","hit":3,"rew":1,"score":1.4723124519757878}]
```
Это массив, он отсортирован по параметру score.

There's a couple of algorithms for MAB but we only have UCB1 implemented for now. We would love to have more algorithms. Fell free to send a push request.
Также можно запросить статистику по переданным "рукам", при помощи Post запроса с массивом "рук"

# Clients

## Javascript
Пример:

- [angular-bandit-client](https://github.com/peleteiro/angular-bandit-client)
```
curl -X POST --data '[{"arm":"ads 2"},{"arm":"1"}]' -H "Content-Type: application/json" http://localhost:3000/stats/domainid42/3

# Sample Project
Ответ:
[{"arm":"1","hit":0,"rew":0,"score":100},{"arm":"ads 2","hit":3,"rew":2,"score":1.5224751688711062}]
```

See [https://github.com/peleteiro/angular-bandit-client/tree/master/example](https://github.com/peleteiro/angular-bandit-client/tree/master/example).
## Debug

Для запуска в режиме отладки необходимо передать флаг debug=true

# Contributing to bandit-server
Пример отладчика:

We encourage you to contribute to bandit-server! Please check out the guidelines about how to proceed.
```
./bandit-server --debug=true
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)

* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
[GIN-debug] GET / --> main.ok (3 handlers)
[GIN-debug] GET /stats/:group/:count --> main.stats (3 handlers)
[GIN-debug] POST /:param/:group --> main.write (3 handlers)
[{ads 1 1} {ads 2 1}]
[GIN] 2018/11/20 - 19:06:34 | 200 | 2.767846ms | ::1 | POST /hits/domainid42
[{ads 1 1} {ads 2 1}]
[GIN] 2018/11/20 - 19:06:56 | 200 | 386.706µs | ::1 | POST /hits/domainid42
[{ads 2 1}]
[GIN] 2018/11/20 - 19:07:12 | 200 | 2.396616ms | ::1 | POST /rewards/domainid42
[GIN] 2018/11/20 - 19:07:21 | 200 | 710.533µs | ::1 | GET /stats/domainid42/2
```

* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it

* Fork the project
## Backup

* Start a feature/bugfix branch

* Commit and push until you are happy with your contribution
Make sure to add tests for the feature/bugfix. This is important so I don't break it in a future version unintentionally.
Надо выполнить запрос:
```
curl -X GET http://localhost:3000/backup/backup
```
последний параметр - backup - директория.

* Please try not to mess with the Makefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate it to its own commit so I can cherry-pick around it.
Ответ - 200 ok

# License

Expand Down
Loading