Skip to content
This repository has been archived by the owner on Aug 22, 2019. It is now read-only.

Commit

Permalink
Merge branch 'master' into 0.13migration
Browse files Browse the repository at this point in the history
  • Loading branch information
MetcalfeTom committed Feb 6, 2019
2 parents 508f8a7 + 3cfbad4 commit 5c94151
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 15 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ This project adheres to `Semantic Versioning`_ starting with version 0.2.0.

Added
-----
- ``tf.ConfigProto`` configuration can now be specified
for tensorflow based pipelines
- open api spec for the Rasa Core SDK action server


Changed
-------
- ``MessageProcessor`` now also passes ``message_id`` to the interpreter
Expand Down
2 changes: 1 addition & 1 deletion docs/connectors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ you need to supply a ``credentials.yml`` with the following content:
slack:
slack_token: "xoxb-286425452756-safjasdf7sl38KLls"
slack_channel: "@my_channel"
slack_channel: "#my_channel"
The endpoint for receiving slack messages is
Expand Down
23 changes: 17 additions & 6 deletions rasa_core/policies/embedding_policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,13 +273,13 @@ def _load_visual_params(self, config: Dict[Text, Any]) -> None:
self.evaluate_every_num_epochs = config['evaluate_every_num_epochs']
if self.evaluate_every_num_epochs < 1:
self.evaluate_every_num_epochs = self.epochs

self.evaluate_on_num_examples = config['evaluate_on_num_examples']

def _load_params(self, **kwargs: Dict[Text, Any]) -> None:
config = copy.deepcopy(self.defaults)
config.update(kwargs)

self._tf_config = self._load_tf_config(config)
self._load_nn_architecture_params(config)
self._load_embedding_params(config)
self._load_regularization_params(config)
Expand Down Expand Up @@ -898,7 +898,7 @@ def _tf_loss(self,

# maximize similarity returned by time attention wrapper
for sim_to_add in sims_rnn_to_max:
loss += tf.maximum(0., - sim_to_add + 1.)
loss += tf.maximum(0., 1. - sim_to_add)

# mask loss for different length sequences
loss *= mask
Expand Down Expand Up @@ -1053,7 +1053,7 @@ def train(self,
self._train_op = tf.train.AdamOptimizer(
learning_rate=0.001, epsilon=1e-16).minimize(loss)
# train tensorflow graph
self.session = tf.Session()
self.session = tf.Session(config=self._tf_config)

self._train_tf(session_data, loss, mask)

Expand Down Expand Up @@ -1410,10 +1410,15 @@ def persist(self, path: Text) -> None:
saver = tf.train.Saver()
saver.save(self.session, checkpoint)

dump_path = os.path.join(path, file_name + ".encoded_all_actions.pkl")
with io.open(dump_path, 'wb') as f:
encoded_actions_file = os.path.join(
path, file_name + ".encoded_all_actions.pkl")
with io.open(encoded_actions_file, 'wb') as f:
pickle.dump(self.encoded_all_actions, f)

tf_config_file = os.path.join(path, file_name + ".tf_config.pkl")
with io.open(tf_config_file, 'wb') as f:
pickle.dump(self._tf_config, f)

@staticmethod
def load_tensor(name: Text) -> Optional[tf.Tensor]:
tensor_list = tf.get_collection(name)
Expand All @@ -1437,9 +1442,15 @@ def load(cls, path: Text) -> 'EmbeddingPolicy':
if not os.path.exists(checkpoint + '.meta'):
return cls(featurizer=featurizer)

tf_config_file = os.path.join(
path, "{}.tf_config.pkl".format(file_name))

with io.open(tf_config_file, 'rb') as f:
_tf_config = pickle.load(f)

graph = tf.Graph()
with graph.as_default():
sess = tf.Session()
sess = tf.Session(config=_tf_config)
saver = tf.train.import_meta_graph(checkpoint + '.meta')

saver.restore(sess, checkpoint)
Expand Down
32 changes: 25 additions & 7 deletions rasa_core/policies/keras_policy.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import copy
import io
import json
import logging
import os
Expand All @@ -15,6 +16,11 @@
from rasa_core.policies.policy import Policy
from rasa_core.trackers import DialogueStateTracker

try:
import cPickle as pickle
except ImportError:
import pickle

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -63,6 +69,7 @@ def _load_params(self, **kwargs: Dict[Text, Any]) -> None:
config.update(kwargs)

# filter out kwargs that are used explicitly
self._tf_config = self._load_tf_config(config)
self.rnn_size = config.pop('rnn_size')
self.epochs = config.pop('epochs')
self.batch_size = config.pop('batch_size')
Expand Down Expand Up @@ -155,7 +162,8 @@ def train(self,
with self.graph.as_default():
# set random seed in tf
tf.set_random_seed(self.random_seed)
self.session = tf.Session()
self.session = tf.Session(config=self._tf_config)

with self.session.as_default():
if self.model is None:
self.model = self.model_architecture(shuffled_X.shape[1:],
Expand Down Expand Up @@ -231,14 +239,19 @@ def persist(self, path: Text) -> None:
meta = {"model": "keras_model.h5",
"epochs": self.current_epoch}

config_file = os.path.join(path, 'keras_policy.json')
utils.dump_obj_as_json_to_file(config_file, meta)
meta_file = os.path.join(path, 'keras_policy.json')
utils.dump_obj_as_json_to_file(meta_file, meta)

model_file = os.path.join(path, meta['model'])
# makes sure the model directory exists
utils.create_dir_for_file(model_file)
with self.graph.as_default(), self.session.as_default():
self.model.save(model_file, overwrite=True)

tf_config_file = os.path.join(
path, "keras_policy.tf_config.pkl")
with io.open(tf_config_file, 'wb') as f:
pickle.dump(self._tf_config, f)
else:
warnings.warn("Persist called without a trained model present. "
"Nothing to persist then!")
Expand All @@ -249,15 +262,20 @@ def load(cls, path: Text) -> 'KerasPolicy':

if os.path.exists(path):
featurizer = TrackerFeaturizer.load(path)
meta_path = os.path.join(path, "keras_policy.json")
if os.path.isfile(meta_path):
meta = json.loads(utils.read_file(meta_path))
meta_file = os.path.join(path, "keras_policy.json")
if os.path.isfile(meta_file):
meta = json.loads(utils.read_file(meta_file))

tf_config_file = os.path.join(
path, "keras_policy.tf_config.pkl")
with io.open(tf_config_file, 'rb') as f:
_tf_config = pickle.load(f)

model_file = os.path.join(path, meta["model"])

graph = tf.Graph()
with graph.as_default():
session = tf.Session()
session = tf.Session(config=_tf_config)
with session.as_default():
model = load_model(model_file)

Expand Down
13 changes: 12 additions & 1 deletion rasa_core/policies/policy.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import copy
import logging
import tensorflow as tf
from typing import (
Any, List, Optional, Text, Dict, Callable)

Expand Down Expand Up @@ -28,7 +29,17 @@ def _create_featurizer(cls, featurizer=None):
else:
return cls._standard_featurizer()

def __init__(self, featurizer: Optional[TrackerFeaturizer] = None) -> None:
@staticmethod
def _load_tf_config(config: Dict[Text, Any]) -> Optional[tf.ConfigProto]:
"""Prepare tf.ConfigProto for training"""
if config.get("tf_config") is not None:
return tf.ConfigProto(**config.pop("tf_config"))
else:
return None

def __init__(self,
featurizer: Optional[TrackerFeaturizer] = None
) -> None:
self.__featurizer = self._create_featurizer(featurizer)

@property
Expand Down
71 changes: 71 additions & 0 deletions tests/test_policies.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,34 @@
from tests.utilities import read_dialogue_file, user_uttered, get_tracker


def tf_defaults():
return {
"tf_config": {
"device_count": {"CPU": 4},
# tell tf.Session to use CPU limit, if you have
# more CPU, you can increase this value appropriately
"inter_op_parallelism_threads": 0,
# the number of threads in the thread pool available
# for each process for blocking operation nodes set to 0
# to allow the system to select the appropriate value.
"intra_op_parallelism_threads": 0, # tells the degree of thread
# parallelism of the tf.Session operation.
# the smaller the value, the less reuse the thread will have
# and the more likely it will use more CPU cores.
# if the value is 0,
# tensorflow will automatically select an appropriate value.
"gpu_options": {"allow_growth": True}
# if set True, will try to allocate
# as much GPU memory as possible to support running
}
}


def session_config():
import tensorflow as tf
return tf.ConfigProto(**tf_defaults()["tf_config"])


def train_trackers(domain):
trackers = training.load_data(
DEFAULT_STORIES_FILE,
Expand Down Expand Up @@ -93,6 +121,15 @@ def test_persist_and_load_empty_policy(self, tmpdir):
loaded = empty_policy.__class__.load(tmpdir.strpath)
assert loaded is not None

def test_tf_config(self, trained_policy, tmpdir):
if hasattr(trained_policy, 'session'):
# noinspection PyProtectedMember
assert trained_policy.session._config is None
trained_policy.persist(tmpdir.strpath)
loaded = trained_policy.__class__.load(tmpdir.strpath)
# noinspection PyProtectedMember
assert loaded.session._config is None


class TestKerasPolicy(PolicyTestCollection):

Expand All @@ -102,6 +139,22 @@ def create_policy(self, featurizer):
return p


class TestKerasPolicyWithTfConfig(PolicyTestCollection):

@pytest.fixture(scope="module")
def create_policy(self, featurizer):
p = KerasPolicy(featurizer, **tf_defaults())
return p

def test_tf_config(self, trained_policy, tmpdir):
# noinspection PyProtectedMember
assert trained_policy.session._config == session_config()
trained_policy.persist(tmpdir.strpath)
loaded = trained_policy.__class__.load(tmpdir.strpath)
# noinspection PyProtectedMember
assert loaded.session._config == session_config()


class TestFallbackPolicy(PolicyTestCollection):

@pytest.fixture(scope="module")
Expand Down Expand Up @@ -331,6 +384,24 @@ def create_policy(self, featurizer):
return p


class TestEmbeddingPolicyWithTfConfig(PolicyTestCollection):

@pytest.fixture(scope="module")
def create_policy(self, featurizer):
# use standard featurizer from EmbeddingPolicy,
# since it is using FullDialogueTrackerFeaturizer
p = EmbeddingPolicy(**tf_defaults())
return p

def test_tf_config(self, trained_policy, tmpdir):
# noinspection PyProtectedMember
assert trained_policy.session._config == session_config()
trained_policy.persist(tmpdir.strpath)
loaded = trained_policy.__class__.load(tmpdir.strpath)
# noinspection PyProtectedMember
assert loaded.session._config == session_config()


class TestFormPolicy(PolicyTestCollection):

@pytest.fixture(scope="module")
Expand Down

0 comments on commit 5c94151

Please sign in to comment.