//  [python]
def __init__(self, inputs, hparams, mode, force_argmax=False):
        self.word_bow_loss = tf.constant(0.0)
        vocab_size = hparams['tgt_vocab_size']
        self.force_argmax = force_argmax

        self.mode = mode
        self.dropout = inputs['dropout']
        self._word2entity = inputs['word2entity']
        self._entity2word = inputs['entity2word']
        self._fact_distribution = hparams.get('fact_distribution', False)

        # 鉴别是词，还是Entity Word 还是什么）
        id2type = tf.constant([0] * vocab_size + [1] * hparams['copy_token_nums'] + [2] * hparams['entity_token_nums'],
                              dtype=tf.int32)
        self._embedding_id2type = tf.one_hot(id2type, depth=3, dtype=tf.float32)
        self._inputs_for_encoder = inputs['inputs_for_encoder']
        self._inputs_for_decoder = inputs['inputs_for_decoder']
        self._outputs_for_decoder = inputs['outputs_for_decoder']
        self._outputs_type_for_decoder = tf.nn.embedding_lookup(id2type, self._outputs_for_decoder)
        self.batch_size = tf.to_float(tf.shape(self._inputs_for_encoder)[0])

        # 都是相对位置
        self._cue_fact_abs_idx = inputs['cue_fact']
        self._cue_fact_idx = tf.squeeze(inputs['cue_fact'], -1)
        self._neg_fact_idx = tf.squeeze(inputs['neg_fact'], -1)

        self._lengths_for_fact_candidate = inputs['lengths_for_facts']

        self._lengths_for_encoder = inputs['lengths_for_encoder']
        self._lengths_for_decoder = inputs['lengths_for_decoder']

        self._embedding_vocab = inputs['embedding_vocab']
        self._embedding_entity = inputs['embedding_entity']
        self._embedding_fact = inputs['embedding_fact']
        if hparams.get('flexka_mask_fact_tgt_part', False) is True:
            self._embedding_fact_wo_tgt = tf.slice(self._embedding_fact, [0, 0], [-1, 2 * hparams['entity_dim']])

        self._fact_entity_in_response = inputs['fact_entity_in_response']
        self._fact_entity_in_post = inputs['fact_entity_in_post']
        self._fact_candidate = inputs['inputs_for_facts']

        self._max_fact_num = tf.shape(self._fact_candidate)[-1]

        # => [batch, fact_num]
        zero_mask = tf.one_hot(tf.zeros([self.batch_size], dtype=tf.int32)
                               , depth=vocab_size,
                               on_value=0.0, off_value=1.0,
                               dtype=tf.float32)

        bag_of_words_input = tf.slice(self._inputs_for_decoder, [0, 1], [-1, -1])
        word_bow = tf.reduce_max(tf.one_hot(bag_of_words_input, depth=vocab_size,
                                            on_value=1.0, off_value=0.0,
                                            dtype=tf.float32), 1)
        self._golden_word_bow = tf.minimum(word_bow, zero_mask)

        # => [batch, fact_num]
        zero_mask = tf.one_hot(tf.zeros([self.batch_size], dtype=tf.int32)
                               , depth=self._max_fact_num,
                               on_value=0.0, off_value=1.0,
                               dtype=tf.float32)
        golden_fact_bow = tf.reduce_max(tf.one_hot(inputs['cue_fact'], depth=self._max_fact_num,
                                                   on_value=1.0, off_value=0.0,
                                                   dtype=tf.float32), 1)
        self._golden_fact_bow = tf.minimum(golden_fact_bow, zero_mask)

        if hparams.get('add_word_embedding_to_fact', False):  # TODO Check 是否有必要保留
            response_words = tf.nn.embedding_lookup(self._entity2word, self._fact_entity_in_response)
            response_embedding = tf.nn.embedding_lookup(self._embedding_vocab, response_words)

            post_words = tf.nn.embedding_lookup(self._entity2word, self._fact_entity_in_post)
            post_embedding = tf.nn.embedding_lookup(self._embedding_vocab, post_words)

            self._embedding_fact = tf.concat([self._embedding_fact, post_embedding, response_embedding], axis=-1)
            if hparams.get('flexka_mask_fact_tgt_part', False) is True:
                self._embedding_fact_wo_tgt = tf.concat([self._embedding_fact_wo_tgt, post_embedding], axis=-1)

        self._fact_candidate_embedding = tf.nn.embedding_lookup(self._embedding_fact, self._fact_candidate)

        if hparams.get('flexka_mask_fact_tgt_part', False):
            self._fact_candidate_embedding_wo_tgt = tf.nn.embedding_lookup(self._embedding_fact_wo_tgt,
                                                                           self._fact_candidate)

        # inputs
        self._input_embeddings_for_encoder = tf.nn.embedding_lookup(self._embedding_vocab, self._inputs_for_encoder)
        self._input_entities_for_encoder = inputs['entity_inputs_for_encoder']
        self._input_entity_embeddings_for_encoder = tf.nn.embedding_lookup(self._embedding_entity,
                                                                           self._input_entities_for_encoder)

        self._input_embeddings_for_decoder = tf.nn.embedding_lookup(self._embedding_vocab, self._inputs_for_decoder)
        self._input_entities_for_decoder = inputs['entity_inputs_for_decoder']
        self._input_entity_embeddings_for_decoder = tf.nn.embedding_lookup(self._embedding_entity,
                                                                           self._input_entities_for_decoder)

        self._projection_layer = tf.layers.Dense(vocab_size, use_bias=False)
        self.predict_count = tf.reduce_sum(self._lengths_for_decoder)

        self.src_vocab_table = inputs['src_vocab_table']
        self.tgt_vocab_table = inputs['tgt_vocab_table']
        self.reverse_target_vocab_table = inputs['reverse_target_vocab_table']

        self.hparams = hparams

        self.global_step = tf.Variable(0, trainable=False)
        self.epoch_step = tf.Variable(0, trainable=False)
        self.next_epoch = tf.assign_add(self.epoch_step, 1)

        self.reset_epoch = tf.assign(self.epoch_step, 0)
        self.rest_global_step = tf.assign(self.global_step, 0)

        self.learning_rate = tf.placeholder(name='learning_rate', dtype=tf.float32)
        self.inference_mode = tf.placeholder(name='learning_rate', dtype=tf.bool)
        # warm-up
        self.learning_rate = model_helper.get_learning_rate_warmup(self.learning_rate, self.global_step, hparams)
        # decay
        self.learning_rate = model_helper.get_learning_rate_decay(self.learning_rate, self.global_step, hparams)

        self.create_model()
        if self.mode == model_helper.TRAIN:
            self.create_update_op()

        # Saver
        self.saver = tf.train.Saver(
            tf.global_variables(), max_to_keep=2)
        self.ppl_saver = tf.train.Saver(
            tf.global_variables(), max_to_keep=hparams['num_keep_ckpts'])