Update upload model
This commit is contained in:
parent
9c8482ad5f
commit
a5ae7a9d5b
|
@ -48,7 +48,6 @@ The backend can be installed with
|
||||||
```
|
```
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
cd server
|
cd server
|
||||||
python manage.py makemigrations
|
|
||||||
python manage.py migrate
|
python manage.py migrate
|
||||||
cd ..
|
cd ..
|
||||||
```
|
```
|
||||||
|
|
44
docs/api.md
44
docs/api.md
|
@ -16,30 +16,32 @@ The definitions of the fields are as follows:
|
||||||
* `payoff`: Float. The payoff of the agent in the first seat.
|
* `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\]
|
* `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 |
|
| 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/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\_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\_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/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 |
|
| 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 |
|
| 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/delete\_agent | `name` | Delete the agent of the given name |
|
||||||
| GET | tournament/list\_uploaded\_agents | `game` | list all the uploaded agents |
|
| GET | tournament/list\_uploaded\_agents | `game` | list all the uploaded agents |
|
||||||
| GET | tournament/list\_baseline\_agents | `game` | list all the baseline agents |
|
| GET | tournament/list\_baseline\_agents | `game` | list all the baseline agents |
|
||||||
|
| GET | download\_examples | `name` | download the example agents |
|
||||||
|
|
||||||
### Example API
|
### Example API
|
||||||
| API | Description |
|
| 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/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/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&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\_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 | 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\_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/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\_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/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
|
## Registered Models
|
||||||
Some models have been pre-registered as baselines
|
Some models have been pre-registered as baselines
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -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
|
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')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('name', models.CharField(max_length=100)),
|
('name', models.CharField(max_length=100)),
|
||||||
('game', models.CharField(max_length=100)),
|
('game', models.CharField(max_length=100)),
|
||||||
('entry', models.CharField(max_length=100)),
|
|
||||||
('f', models.FileField(upload_to='uploaded_agents')),
|
('f', models.FileField(upload_to='uploaded_agents')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -43,9 +43,6 @@ class UploadedAgent(models.Model):
|
||||||
# The game of the agent
|
# The game of the agent
|
||||||
game = models.CharField(max_length=100)
|
game = models.CharField(max_length=100)
|
||||||
|
|
||||||
# The class name of the Model
|
|
||||||
entry = models.CharField(max_length=100)
|
|
||||||
|
|
||||||
# File
|
# File
|
||||||
f = models.FileField(upload_to='uploaded_agents')
|
f = models.FileField(upload_to='uploaded_agents')
|
||||||
|
|
||||||
|
|
|
@ -12,4 +12,5 @@ urlpatterns = [
|
||||||
path('delete_agent', views.delete_agent, name='delete_agent'),
|
path('delete_agent', views.delete_agent, name='delete_agent'),
|
||||||
path('list_uploaded_agents', views.list_uploaded_agents, name='list_uploaded_agents'),
|
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('list_baseline_agents', views.list_baseline_agents, name='list_baseline_agents'),
|
||||||
|
path('download_examples', views.download_examples, name='download_examples'),
|
||||||
]
|
]
|
||||||
|
|
|
@ -3,9 +3,11 @@ import os
|
||||||
import importlib.util
|
import importlib.util
|
||||||
import math
|
import math
|
||||||
import copy
|
import copy
|
||||||
|
import zipfile
|
||||||
|
import shutil
|
||||||
|
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse, Http404
|
||||||
from django.db import transaction
|
from django.db import transaction
|
||||||
from django.core import serializers
|
from django.core import serializers
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
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)
|
path = os.path.join(settings.MEDIA_ROOT, agent.f.name)
|
||||||
name = agent.name
|
name = agent.name
|
||||||
game = agent.game
|
game = agent.game
|
||||||
entry = agent.entry
|
target_path = os.path.join(os.path.abspath(os.path.join(path, os.pardir)), name)
|
||||||
module_name = path.split('/')[-1].split('.')[0]
|
module_name = 'model'
|
||||||
spec = importlib.util.spec_from_file_location(module_name, path)
|
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)
|
module = importlib.util.module_from_spec(spec)
|
||||||
spec.loader.exec_module(module)
|
spec.loader.exec_module(module)
|
||||||
M = getattr(module, entry)
|
M = getattr(module, entry)
|
||||||
|
@ -40,7 +43,7 @@ def _get_model_ids_all():
|
||||||
self._entry_point = M
|
self._entry_point = M
|
||||||
|
|
||||||
def load(self):
|
def load(self):
|
||||||
model = self._entry_point()
|
model = self._entry_point(target_path)
|
||||||
return model
|
return model
|
||||||
rlcard.models.registration.model_registry.model_specs[name] = ModelSpec()
|
rlcard.models.registration.model_registry.model_specs[name] = ModelSpec()
|
||||||
MODEL_IDS_ALL[game].append(name)
|
MODEL_IDS_ALL[game].append(name)
|
||||||
|
@ -92,7 +95,6 @@ def query_agent_payoff(request):
|
||||||
if not 'name' in request.GET:
|
if not 'name' in request.GET:
|
||||||
return HttpResponse(json.dumps({'value': -2, 'info': 'name should be given'}))
|
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'))
|
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'])
|
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}))
|
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']
|
f = request.FILES['model']
|
||||||
name = request.POST['name']
|
name = request.POST['name']
|
||||||
game = request.POST['game']
|
game = request.POST['game']
|
||||||
entry = request.POST['entry']
|
|
||||||
if UploadedAgent.objects.filter(name=name).exists():
|
if UploadedAgent.objects.filter(name=name).exists():
|
||||||
return HttpResponse(json.dumps({'value': -1, 'info': '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()
|
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'}))
|
return HttpResponse(json.dumps({'value': 0, 'info': 'success'}))
|
||||||
|
|
||||||
def delete_agent(request):
|
def delete_agent(request):
|
||||||
|
@ -146,9 +151,16 @@ def delete_agent(request):
|
||||||
if not UploadedAgent.objects.filter(name=name).exists():
|
if not UploadedAgent.objects.filter(name=name).exists():
|
||||||
return HttpResponse(json.dumps({'value': -1, 'info': 'name not 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(agent0=name).delete()
|
||||||
Game.objects.filter(agent1=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'}))
|
return HttpResponse(json.dumps({'value': 0, 'info': 'success'}))
|
||||||
|
|
||||||
def list_uploaded_agents(request):
|
def list_uploaded_agents(request):
|
||||||
|
@ -170,3 +182,14 @@ def auto_delete_file_on_delete(sender, instance, **kwargs):
|
||||||
if instance.f:
|
if instance.f:
|
||||||
if os.path.isfile(instance.f.path):
|
if os.path.isfile(instance.f.path):
|
||||||
os.remove(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
|
||||||
|
|
|
@ -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
|
|
Loading…
Reference in New Issue