Update upload model

This commit is contained in:
Daochen Zha 2020-12-11 12:29:18 -06:00
parent 9c8482ad5f
commit a5ae7a9d5b
9 changed files with 57 additions and 120 deletions

View File

@ -48,7 +48,6 @@ The backend can be installed with
```
pip install -r requirements.txt
cd server
python manage.py makemigrations
python manage.py migrate
cd ..
```

View File

@ -16,30 +16,32 @@ The definitions of the fields are as follows:
* `payoff`: Float. The payoff of the agent in the first seat.
* `index`: Integer. The index of the game of the same environent and same agent. It is in the range \[0, eval_num-1\]
| type | Resource | Parameters | Description |
|------|---------------------------|------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
| GET | tournament/launch | `eval_num`, `name` | Launch tournment on the game. Each pair of models will play `eval_num` times. Results will be saved in database. |
| GET | tournament/query\_game | `name`, `index`, `agent0`, `agent1`, `win`, `payoff`, `elements_every_page`, `page_index` | Query the games with the given parameters |
| GET | tournament/query\_payoff | `name`, `agent0`, `agent1`, `payoff` | Query the payoffs with the given parameters |
| GET | tournament/query\_agent\_payoff | `name`, `elements_every_page`, `page_index`, | Query the payoffs of all the agents |
| GET | tournament/replay | `name`, `agent0`, `agent1`, `index` | Return the replay data |
| POST | tournament/upload\_agent | `model`(Python file), `name`, `game`, `entry` | Upload a model file. `name` is model ID, `entry` is the class name of the model |
| GET | tournament/delete\_agent | `name` | Delete the agent of the given name |
| GET | tournament/list\_uploaded\_agents | `game` | list all the uploaded agents |
| GET | tournament/list\_baseline\_agents | `game` | list all the baseline agents |
| type | Resource | Parameters | Description |
|------|-------------------------------------|-------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
| GET | tournament/launch | `eval_num`, `name` | Launch tournment on the game. Each pair of models will play `eval_num` times. Results will be saved in database. |
| GET | tournament/query\_game | `name`, `index`, `agent0`, `agent1`, `win`, `payoff`, `elements_every_page`, `page_index` | Query the games with the given parameters |
| GET | tournament/query\_payoff | `name`, `agent0`, `agent1`, `payoff` | Query the payoffs with the given parameters |
| GET | tournament/query\_agent\_payoff | `name`, `elements_every_page`, `page_index`, | Query the payoffs of all the agents |
| GET | tournament/replay | `name`, `agent0`, `agent1`, `index` | Return the replay data |
| POST | tournament/upload\_agent | `model`(Python file), `name`, `game`, `entry` | Upload a model file. `name` is model ID, `entry` is the class name of the model |
| GET | tournament/delete\_agent | `name` | Delete the agent of the given name |
| GET | tournament/list\_uploaded\_agents | `game` | list all the uploaded agents |
| GET | tournament/list\_baseline\_agents | `game` | list all the baseline agents |
| GET | download\_examples | `name` | download the example agents |
### Example API
| API | Description |
|-----------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------|
| http://127.0.0.1:8000/tournament/launch?eval_num=200&name=leduc-holdem | Evaluate on Leduc Holdem with 200 games for each pair of models |
| API | Description |
|------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------|
| http://127.0.0.1:8000/tournament/launch?eval\_num=200&name=leduc-holdem | Evaluate on Leduc Holdem with 200 games for each pair of models |
| http://127.0.0.1:8000/tournament/replay?name=leduc-holdem&agent0=leduc-holdem-rule-v1&agent1=leduc-holdem-cfr&index=3 | Obtain the replay data between rule model and CFR model. Obtain the data of the 3rd game |
| http://127.0.0.1:8000/tournament/query_game&elements_every_page=10&page_index=0 | Get all the game data |
| http://127.0.0.1:8000/tournament/query_game?name=leduc-holdem&elements_every_page=10&page_index=0 | Get all the game data of Leduc Holdem |
| http://127.0.0.1:8000/tournament/query_payoff | Get all the payoffs |
| http://127.0.0.1:8000/tournament/query_payoff?agent0=leduc-holdem-cfr&agent1=leduc-holdem-rule-v1 | Get all the payoffs between rule and CFR models |
| http://127.0.0.1:8000/tournament/query_agent_payoff?name=leduc-holdem&elements_every_page=1&page_index=1 | Get the payoffs of all the agents of leduc-holdem |
| http://127.0.0.1:8000/tournament/list_uploaded_agents?game=leduc-holdem | List the uploaded agents of leduc-holdem |
| http://127.0.0.1:8000/tournament/list_baseline_agents?game=leduc-holdem | List the baseline agents of leduc-holdem |
| http://127.0.0.1:8000/tournament/query\_game&elements\_every\_page=10&page\_index=0 | Get all the game data |
| http://127.0.0.1:8000/tournament/query\_game?name=leduc-holdem&elements\_every\_page=10&page\_index=0 | Get all the game data of Leduc Holdem |
| http://127.0.0.1:8000/tournament/query\_payoff | Get all the payoffs |
| http://127.0.0.1:8000/tournament/query\_payoff?agent0=leduc-holdem-cfr&agent1=leduc-holdem-rule-v1 | Get all the payoffs between rule and CFR models |
| http://127.0.0.1:8000/tournament/query\_agent\_payoff?name=leduc-holdem&elements\_every\_page=1&page\_index=1 | Get the payoffs of all the agents of leduc-holdem |
| http://127.0.0.1:8000/tournament/list\_uploaded\_agents?game=leduc-holdem | List the uploaded agents of leduc-holdem |
| http://127.0.0.1:8000/tournament/list\_baseline\_agents?game=leduc-holdem | List the baseline agents of leduc-holdem |
| http://127.0.0.1:8000/tournament/download\_examples?name=example\_luduc\_nfsp\_model | Download the NFSP example model for Leduc Hold'em |
## Registered Models
Some models have been pre-registered as baselines

View File

@ -1,4 +1,4 @@
# Generated by Django 2.2.12 on 2020-05-13 02:29
# Generated by Django 3.1.4 on 2020-12-11 17:43
from django.db import migrations, models
@ -40,7 +40,6 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('game', models.CharField(max_length=100)),
('entry', models.CharField(max_length=100)),
('f', models.FileField(upload_to='uploaded_agents')),
],
),

View File

@ -43,9 +43,6 @@ class UploadedAgent(models.Model):
# The game of the agent
game = models.CharField(max_length=100)
# The class name of the Model
entry = models.CharField(max_length=100)
# File
f = models.FileField(upload_to='uploaded_agents')

View File

@ -12,4 +12,5 @@ urlpatterns = [
path('delete_agent', views.delete_agent, name='delete_agent'),
path('list_uploaded_agents', views.list_uploaded_agents, name='list_uploaded_agents'),
path('list_baseline_agents', views.list_baseline_agents, name='list_baseline_agents'),
path('download_examples', views.download_examples, name='download_examples'),
]

View File

@ -3,9 +3,11 @@ import os
import importlib.util
import math
import copy
import zipfile
import shutil
from django.shortcuts import render
from django.http import HttpResponse
from django.http import HttpResponse, Http404
from django.db import transaction
from django.core import serializers
from django.views.decorators.csrf import csrf_exempt
@ -27,9 +29,10 @@ def _get_model_ids_all():
path = os.path.join(settings.MEDIA_ROOT, agent.f.name)
name = agent.name
game = agent.game
entry = agent.entry
module_name = path.split('/')[-1].split('.')[0]
spec = importlib.util.spec_from_file_location(module_name, path)
target_path = os.path.join(os.path.abspath(os.path.join(path, os.pardir)), name)
module_name = 'model'
entry = 'Model'
spec = importlib.util.spec_from_file_location(module_name, os.path.join(target_path, module_name+'.py'))
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
M = getattr(module, entry)
@ -40,7 +43,7 @@ def _get_model_ids_all():
self._entry_point = M
def load(self):
model = self._entry_point()
model = self._entry_point(target_path)
return model
rlcard.models.registration.model_registry.model_specs[name] = ModelSpec()
MODEL_IDS_ALL[game].append(name)
@ -92,7 +95,6 @@ def query_agent_payoff(request):
if not 'name' in request.GET:
return HttpResponse(json.dumps({'value': -2, 'info': 'name should be given'}))
result = list(Payoff.objects.filter(name=request.GET['name']).values('agent0').annotate(payoff = Avg('payoff')).order_by('-payoff'))
print(result)
result, total_page, total_row = _get_page(result, request.GET['elements_every_page'], request.GET['page_index'])
return HttpResponse(json.dumps({'value': 0, 'data': result, 'total_page': total_page, 'total_row': total_row}))
@ -132,12 +134,15 @@ def upload_agent(request):
f = request.FILES['model']
name = request.POST['name']
game = request.POST['game']
entry = request.POST['entry']
if UploadedAgent.objects.filter(name=name).exists():
return HttpResponse(json.dumps({'value': -1, 'info': 'name exists'}))
a = UploadedAgent(name=name, game=game, f=f, entry=entry)
a = UploadedAgent(name=name, game=game, f=f)
a.save()
path = os.path.join(settings.MEDIA_ROOT, a.f.name)
target_path = os.path.join(os.path.abspath(os.path.join(path, os.pardir)), name)
with zipfile.ZipFile(path, 'r') as zip_ref:
zip_ref.extractall(target_path)
return HttpResponse(json.dumps({'value': 0, 'info': 'success'}))
def delete_agent(request):
@ -146,9 +151,16 @@ def delete_agent(request):
if not UploadedAgent.objects.filter(name=name).exists():
return HttpResponse(json.dumps({'value': -1, 'info': 'name not exists'}))
UploadedAgent.objects.filter(name=name).delete()
agents = UploadedAgent.objects.filter(name=name)
path = os.path.join(settings.MEDIA_ROOT, agents[0].f.name)
target_path = os.path.join(os.path.abspath(os.path.join(path, os.pardir)), name)
shutil.rmtree(target_path)
agents.delete()
Game.objects.filter(agent0=name).delete()
Game.objects.filter(agent1=name).delete()
Payoff.objects.filter(agent0=name).delete()
Payoff.objects.filter(agent1=name).delete()
return HttpResponse(json.dumps({'value': 0, 'info': 'success'}))
def list_uploaded_agents(request):
@ -170,3 +182,14 @@ def auto_delete_file_on_delete(sender, instance, **kwargs):
if instance.f:
if os.path.isfile(instance.f.path):
os.remove(instance.f.path)
def download_examples(request):
if request.method == 'GET':
name = request.GET['name']
file_path = os.path.join(settings.MEDIA_ROOT, 'example_agents', name+'.zip')
if os.path.exists(file_path):
with open(file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type="application/vnd.ms-excel")
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
return response
raise Http404

View File

@ -1,84 +0,0 @@
''' Leduc Hold 'em rule model
'''
import rlcard
from rlcard.models.model import Model
class LeducHoldemRuleAgentV2(object):
''' Leduc Hold 'em Rule agent version 2
'''
def __init__(self):
self.use_raw = True
def step(self, state):
''' Predict the action when given raw state. A simple rule-based AI.
Args:
state (dict): Raw state from the game
Returns:
action (str): Predicted action
'''
legal_actions = state['raw_legal_actions']
state = state['raw_obs']
hand = state['hand']
public_card = state['public_card']
action = 'fold'
'''
When having only 2 hand cards at the game start, choose fold to drop terrible cards:
Acceptable hand cards:
Pairs
AK, AQ, AJ, AT
A9s, A8s, ... A2s(s means flush)
KQ, KJ, QJ, JT
Fold all hand types except those mentioned above to save money
'''
if public_card:
if public_card[1] == hand[1]:
action = 'raise'
else:
action = 'fold'
else:
if hand[0] == 'K':
action = 'raise'
elif hand[0] == 'Q':
action = 'check'
else:
action = 'fold'
#return action
if action in legal_actions:
return action
else:
if action == 'raise':
return 'call'
if action == 'check':
return 'fold'
if action == 'call':
return 'raise'
else:
return action
def eval_step(self, state):
return self.step(state), []
class LeducHoldemRuleModelV2(Model):
''' Leduc holdem Rule Model version 2
'''
def __init__(self):
''' Load pretrained model
'''
env = rlcard.make('leduc-holdem')
rule_agent = LeducHoldemRuleAgentV2()
self.rule_agents = [rule_agent for _ in range(env.player_num)]
@property
def agents(self):
''' Get a list of agents for each position in a the game
Returns:
agents (list): A list of agents
Note: Each agent should be just like RL agent with step and eval_step
functioning well.
'''
return self.rule_agents