Upload 23 files
Browse files- LICENSE +21 -0
- config.json +67 -0
- configuration_deepseek_v32.py +213 -0
- encoding/encoding_dsv32.py +376 -0
- encoding/test_encoding_dsv32.py +56 -0
- encoding/test_input.json +149 -0
- encoding/test_input_search_w_date.json +0 -0
- encoding/test_input_search_wo_date.json +533 -0
- encoding/test_output.txt +112 -0
- encoding/test_output_search_w_date.txt +0 -0
- encoding/test_output_search_wo_date.txt +1069 -0
- generation_config.json +4 -0
- inference/README.md +14 -0
- inference/config_671B_v3.2.json +26 -0
- inference/convert.py +100 -0
- inference/generate.py +186 -0
- inference/kernel.py +274 -0
- inference/model.py +923 -0
- inference/requirements.txt +5 -0
- model.safetensors +3 -0
- modeling_deepseek_v32.py +935 -0
- tokenizer.json +0 -0
- tokenizer_config.json +34 -0
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2023 DeepSeek
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
config.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"DeepseekV32ForCausalLM"
|
| 4 |
+
],
|
| 5 |
+
"attention_bias": false,
|
| 6 |
+
"attention_dropout": 0.0,
|
| 7 |
+
"auto_map": {
|
| 8 |
+
"AutoConfig": "configuration_deepseek_v32.DeepseekV32Config",
|
| 9 |
+
"AutoModelForCausalLM": "modeling_deepseek_v32.DeepseekV32ForCausalLM"
|
| 10 |
+
},
|
| 11 |
+
"dtype": "bfloat16",
|
| 12 |
+
"ep_size": 1,
|
| 13 |
+
"firts_k_dense_replace": 1,
|
| 14 |
+
"head_dim": 2,
|
| 15 |
+
"hidden_act": "silu",
|
| 16 |
+
"hidden_size": 32,
|
| 17 |
+
"index_head_dim": 4,
|
| 18 |
+
"index_n_heads": 4,
|
| 19 |
+
"index_topk": 32,
|
| 20 |
+
"initializer_range": 0.02,
|
| 21 |
+
"intermediate_size": 16,
|
| 22 |
+
"kv_lora_rank": 2,
|
| 23 |
+
"tie_word_embeddings": true,
|
| 24 |
+
"max_position_embeddings": 163840,
|
| 25 |
+
"mlp_layer_types": [
|
| 26 |
+
"dense",
|
| 27 |
+
"sparse"
|
| 28 |
+
],
|
| 29 |
+
"model_type": "deepseek_v32",
|
| 30 |
+
"moe_intermediate_size": 4,
|
| 31 |
+
"moe_layer_freq": 1,
|
| 32 |
+
"n_group": 1,
|
| 33 |
+
"n_routed_experts": 16,
|
| 34 |
+
"n_shared_experts": 1,
|
| 35 |
+
"norm_topk_prob": true,
|
| 36 |
+
"num_attention_heads": 2,
|
| 37 |
+
"num_experts_per_tok": 8,
|
| 38 |
+
"num_hidden_layers": 2,
|
| 39 |
+
"num_key_value_heads": 2,
|
| 40 |
+
"num_nextn_predict_layers": 1,
|
| 41 |
+
"q_lora_rank": 2,
|
| 42 |
+
"qk_head_dim": 6,
|
| 43 |
+
"qk_nope_head_dim": 4,
|
| 44 |
+
"qk_rope_head_dim": 2,
|
| 45 |
+
"rms_norm_eps": 1e-06,
|
| 46 |
+
"rope_interleave": true,
|
| 47 |
+
"rope_scaling": {
|
| 48 |
+
"beta_fast": 32.0,
|
| 49 |
+
"beta_slow": 1.0,
|
| 50 |
+
"factor": 40.0,
|
| 51 |
+
"mscale": 1.0,
|
| 52 |
+
"mscale_all_dim": 1.0,
|
| 53 |
+
"original_max_position_embeddings": 4096,
|
| 54 |
+
"rope_theta": 10000,
|
| 55 |
+
"rope_type": "yarn",
|
| 56 |
+
"type": "yarn"
|
| 57 |
+
},
|
| 58 |
+
"rope_theta": 10000.0,
|
| 59 |
+
"routed_scaling_factor": 2.5,
|
| 60 |
+
"scoring_func": "sigmoid",
|
| 61 |
+
"topk_group": 4,
|
| 62 |
+
"topk_method": "noaux_tc",
|
| 63 |
+
"transformers_version": "4.57.1",
|
| 64 |
+
"use_cache": true,
|
| 65 |
+
"v_head_dim": 2,
|
| 66 |
+
"vocab_size": 129280
|
| 67 |
+
}
|
configuration_deepseek_v32.py
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2026 the HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
from transformers.configuration_utils import PretrainedConfig
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class DeepseekV32Config(PretrainedConfig):
|
| 20 |
+
r"""
|
| 21 |
+
This is the configuration class to store the configuration of a [`DeepseekV32Model`].
|
| 22 |
+
Configuration objects inherit from [`PreTrainedConfig`] and can be used to control the model outputs. Read the
|
| 23 |
+
documentation from [`PretrainedConfig`] for more information.
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
Args:
|
| 27 |
+
vocab_size (`int`, *optional*, defaults to 154880):
|
| 28 |
+
Vocabulary size of the Deep model. Defines the number of different tokens that can be represented by the
|
| 29 |
+
`inputs_ids` passed when calling [`DeepseekV32Model`]
|
| 30 |
+
hidden_size (`int`, *optional*, defaults to 6144):
|
| 31 |
+
Dimension of the hidden representations.
|
| 32 |
+
intermediate_size (`int`, *optional*, defaults to 12288):
|
| 33 |
+
Dimension of the MLP representations.
|
| 34 |
+
moe_intermediate_size (`int`, *optional*, defaults to 2048):
|
| 35 |
+
Dimension of the MoE representations.
|
| 36 |
+
num_hidden_layers (`int`, *optional*, defaults to 78):
|
| 37 |
+
Number of hidden layers in the Transformer decoder.
|
| 38 |
+
num_attention_heads (`int`, *optional*, defaults to 64):
|
| 39 |
+
Number of attention heads for each attention layer in the Transformer decoder.
|
| 40 |
+
num_key_value_heads (`int`, *optional*, defaults to 64):
|
| 41 |
+
This is the number of key_value heads that should be used to implement Grouped Query Attention. If
|
| 42 |
+
`num_key_value_heads=num_attention_heads`, the model will use Multi Head Attention (MHA), if
|
| 43 |
+
`num_key_value_heads=1 the model will use Multi Query Attention (MQA) otherwise GQA is used. When
|
| 44 |
+
converting a multi-head checkpoint to a GQA checkpoint, each group key and value head should be constructed
|
| 45 |
+
by meanpooling all the original heads within that group. For more details, check out [this
|
| 46 |
+
paper](https://huggingface.co/papers/2305.13245). If it is not specified, will default to
|
| 47 |
+
`num_attention_heads`.
|
| 48 |
+
n_shared_experts (`int`, *optional*, defaults to 1):
|
| 49 |
+
Number of shared experts.
|
| 50 |
+
n_routed_experts (`int`, *optional*, defaults to 256):
|
| 51 |
+
Number of routed experts.
|
| 52 |
+
routed_scaling_factor (`float`, *optional*, defaults to 2.5):
|
| 53 |
+
Scaling factor or routed experts.
|
| 54 |
+
kv_lora_rank (`int`, *optional*, defaults to 512):
|
| 55 |
+
Rank of the LoRA matrices for key and value projections.
|
| 56 |
+
q_lora_rank (`int`, *optional*, defaults to 2048):
|
| 57 |
+
Rank of the LoRA matrices for query projections.
|
| 58 |
+
qk_rope_head_dim (`int`, *optional*, defaults to 64):
|
| 59 |
+
Dimension of the query/key heads that use rotary position embeddings.
|
| 60 |
+
v_head_dim (`int`, *optional*, defaults to 256):
|
| 61 |
+
Dimension of the value heads.
|
| 62 |
+
qk_nope_head_dim (`int`, *optional*, defaults to 192):
|
| 63 |
+
Dimension of the query/key heads that don't use rotary position embeddings.
|
| 64 |
+
n_group (`int`, *optional*, defaults to 1):
|
| 65 |
+
Number of groups for routed experts.
|
| 66 |
+
topk_group (`int`, *optional*, defaults to 1):
|
| 67 |
+
Number of selected groups for each token(for each token, ensuring the selected experts is only within `topk_group` groups).
|
| 68 |
+
num_experts_per_tok (`int`, *optional*, defaults to 8):
|
| 69 |
+
Number of selected experts, None means dense model.
|
| 70 |
+
norm_topk_prob (`bool`, *optional*, defaults to `True`):
|
| 71 |
+
Whether to normalize the weights of the routed experts.
|
| 72 |
+
hidden_act (`str` or `function`, *optional*, defaults to `"silu"`):
|
| 73 |
+
The non-linear activation function (function or string) in the decoder.
|
| 74 |
+
max_position_embeddings (`int`, *optional*, defaults to 202752):
|
| 75 |
+
The maximum sequence length that this model might ever be used with.
|
| 76 |
+
initializer_range (`float`, *optional*, defaults to 0.02):
|
| 77 |
+
The standard deviation of the truncated_normal_initializer for initializing all weight matrices.
|
| 78 |
+
rms_norm_eps (`float`, *optional*, defaults to 1e-05):
|
| 79 |
+
The epsilon used by the rms normalization layers.
|
| 80 |
+
use_cache (`bool`, *optional*, defaults to `True`):
|
| 81 |
+
Whether or not the model should return the last key/values attentions (not used by all models). Only
|
| 82 |
+
relevant if `config.is_decoder=True`.
|
| 83 |
+
pad_token_id (`int`, *optional*):
|
| 84 |
+
Padding token id.
|
| 85 |
+
bos_token_id (`int`, *optional*, defaults to 0):
|
| 86 |
+
Beginning of stream token id.
|
| 87 |
+
eos_token_id (`int`, *optional*, defaults to 1):
|
| 88 |
+
End of stream token id.
|
| 89 |
+
tie_word_embeddings (`bool`, *optional*, defaults to `False`):
|
| 90 |
+
Whether to tie weight embeddings
|
| 91 |
+
rope_scaling (`Dict`, *optional*):
|
| 92 |
+
Dictionary containing the scaling configuration for the RoPE embeddings. Currently supports two scaling
|
| 93 |
+
strategies: linear and dynamic. Their scaling factor must be a float greater than 1. The expected format is
|
| 94 |
+
`{"type": strategy name, "factor": scaling factor}`. When using this flag, don't update
|
| 95 |
+
`max_position_embeddings` to the expected new maximum.
|
| 96 |
+
rope_theta (`float`, *optional*, defaults to 10000.0):
|
| 97 |
+
The base period of the RoPE embeddings.
|
| 98 |
+
rope_interleave (`bool`, *optional*, defaults to `True`):
|
| 99 |
+
Whether to interleave the rotary position embeddings.
|
| 100 |
+
first_k_dense_replace (`int`, *optional*, defaults to 3):
|
| 101 |
+
Number of dense layers in shallow layers(embed->dense->dense->...->dense->moe->moe...->lm_head). \--k dense layers--/
|
| 102 |
+
attention_bias (`bool`, defaults to `False`, *optional*, defaults to `False`):
|
| 103 |
+
Whether to use a bias in the query, key, value and output projection layers during self-attention.
|
| 104 |
+
attention_dropout (`float`, *optional*, defaults to 0.0):
|
| 105 |
+
The dropout ratio for the attention probabilities.
|
| 106 |
+
index_topk (`int`, *optional*, defaults to 2048):
|
| 107 |
+
Number of top tokens selected by the indexer for retrieval/attention in each step.
|
| 108 |
+
"""
|
| 109 |
+
|
| 110 |
+
model_type = "deepseek_v32"
|
| 111 |
+
keys_to_ignore_at_inference = ["past_key_values"]
|
| 112 |
+
base_model_tp_plan = { # TODO: only replicate attention layers when > first_k_dense_replace
|
| 113 |
+
"layers.*.mlp.experts.*.gate_proj": "local_colwise",
|
| 114 |
+
"layers.*.mlp.experts.*.up_proj": "local_colwise",
|
| 115 |
+
"layers.*.mlp.experts.*.down_proj": "local_rowwise",
|
| 116 |
+
"layers.*.mlp.experts.*": "local", # each expert is wrapped in a module list
|
| 117 |
+
"layers.*.mlp.shared_experts.gate_proj": "local_colwise",
|
| 118 |
+
"layers.*.mlp.shared_experts.up_proj": "local_colwise",
|
| 119 |
+
"layers.*.mlp.shared_experts.down_proj": "local_rowwise",
|
| 120 |
+
"layers.*.mlp.shared_experts": "local",
|
| 121 |
+
"layers.*.mlp.gate_proj": "local_colwise",
|
| 122 |
+
"layers.*.mlp.up_proj": "local_colwise",
|
| 123 |
+
"layers.*.mlp.down_proj": "local_rowwise",
|
| 124 |
+
"layers.*.mlp": "gather", # This is the only moment where results are gathered
|
| 125 |
+
}
|
| 126 |
+
base_model_pp_plan = {
|
| 127 |
+
"embed_tokens": (["input_ids"], ["inputs_embeds"]),
|
| 128 |
+
"layers": (["hidden_states", "attention_mask"], ["hidden_states"]),
|
| 129 |
+
"norm": (["hidden_states"], ["hidden_states"]),
|
| 130 |
+
}
|
| 131 |
+
|
| 132 |
+
def __init__(
|
| 133 |
+
self,
|
| 134 |
+
vocab_size: int | None = 154880,
|
| 135 |
+
hidden_size: int | None = 6144,
|
| 136 |
+
intermediate_size: int | None = 12288,
|
| 137 |
+
moe_intermediate_size: int | None = 2048,
|
| 138 |
+
num_hidden_layers: int | None = 78,
|
| 139 |
+
num_attention_heads: int | None = 64,
|
| 140 |
+
num_key_value_heads: int | None = 64,
|
| 141 |
+
n_shared_experts: int | None = 1,
|
| 142 |
+
n_routed_experts: int | None = 256,
|
| 143 |
+
routed_scaling_factor: float | None = 2.5,
|
| 144 |
+
kv_lora_rank: int | None = 512,
|
| 145 |
+
q_lora_rank: int | None = 2048,
|
| 146 |
+
qk_rope_head_dim: int | None = 64,
|
| 147 |
+
v_head_dim: int | None = 256,
|
| 148 |
+
qk_nope_head_dim: int | None = 192,
|
| 149 |
+
n_group: int | None = 1,
|
| 150 |
+
topk_group: int | None = 1,
|
| 151 |
+
num_experts_per_tok: int | None = 8,
|
| 152 |
+
norm_topk_prob: bool | None = True,
|
| 153 |
+
hidden_act: str | None = "silu",
|
| 154 |
+
max_position_embeddings: int | None = 202752,
|
| 155 |
+
initializer_range: float | None = 0.02,
|
| 156 |
+
rms_norm_eps: int | None = 1e-5,
|
| 157 |
+
use_cache: bool | None = True,
|
| 158 |
+
pad_token_id: int | None = None,
|
| 159 |
+
bos_token_id: int | None = 0,
|
| 160 |
+
eos_token_id: int | None = 1,
|
| 161 |
+
tie_word_embeddings: bool | None = False,
|
| 162 |
+
rope_scaling: dict = None,
|
| 163 |
+
rope_theta: float =10000.0,
|
| 164 |
+
rope_interleave: bool | None = True,
|
| 165 |
+
first_k_dense_replace: int = 3,
|
| 166 |
+
attention_bias: bool | None = False,
|
| 167 |
+
attention_dropout: float | None = 0.0,
|
| 168 |
+
index_topk: int | None = 2048,
|
| 169 |
+
**kwargs,
|
| 170 |
+
):
|
| 171 |
+
self.vocab_size = vocab_size
|
| 172 |
+
self.max_position_embeddings = max_position_embeddings
|
| 173 |
+
self.hidden_size = hidden_size
|
| 174 |
+
self.intermediate_size = intermediate_size
|
| 175 |
+
self.num_hidden_layers = num_hidden_layers
|
| 176 |
+
self.firts_k_dense_replace = first_k_dense_replace
|
| 177 |
+
|
| 178 |
+
self.moe_intermediate_size = moe_intermediate_size
|
| 179 |
+
self.num_attention_heads = num_attention_heads
|
| 180 |
+
self.n_shared_experts = n_shared_experts
|
| 181 |
+
self.n_routed_experts = n_routed_experts
|
| 182 |
+
self.routed_scaling_factor = routed_scaling_factor
|
| 183 |
+
self.kv_lora_rank = kv_lora_rank
|
| 184 |
+
self.q_lora_rank = q_lora_rank
|
| 185 |
+
self.qk_rope_head_dim = qk_rope_head_dim
|
| 186 |
+
self.v_head_dim = v_head_dim
|
| 187 |
+
self.qk_nope_head_dim = qk_nope_head_dim
|
| 188 |
+
self.qk_head_dim = qk_nope_head_dim + qk_rope_head_dim
|
| 189 |
+
self.head_dim = qk_rope_head_dim
|
| 190 |
+
self.n_group = n_group
|
| 191 |
+
self.topk_group = topk_group
|
| 192 |
+
self.num_experts_per_tok = num_experts_per_tok
|
| 193 |
+
self.norm_topk_prob = norm_topk_prob
|
| 194 |
+
self.rope_interleave = rope_interleave
|
| 195 |
+
self.num_key_value_heads = num_key_value_heads
|
| 196 |
+
self.hidden_act = hidden_act
|
| 197 |
+
self.initializer_range = initializer_range
|
| 198 |
+
self.index_topk = index_topk
|
| 199 |
+
self.rms_norm_eps = rms_norm_eps
|
| 200 |
+
self.use_cache = use_cache
|
| 201 |
+
self.attention_bias = attention_bias
|
| 202 |
+
self.attention_dropout = attention_dropout
|
| 203 |
+
self.rope_scaling = rope_scaling
|
| 204 |
+
self.rope_theta = rope_theta
|
| 205 |
+
self.pad_token_id = pad_token_id
|
| 206 |
+
self.bos_token_id = bos_token_id
|
| 207 |
+
self.eos_token_id = eos_token_id
|
| 208 |
+
self.tie_word_embeddings = tie_word_embeddings
|
| 209 |
+
|
| 210 |
+
super().__init__(**kwargs)
|
| 211 |
+
|
| 212 |
+
|
| 213 |
+
__all__ = ["DeepseekV32Config"]
|
encoding/encoding_dsv32.py
ADDED
|
@@ -0,0 +1,376 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Any, Dict, List, Union, Optional, Tuple
|
| 2 |
+
import copy
|
| 3 |
+
import json
|
| 4 |
+
import re
|
| 5 |
+
|
| 6 |
+
TOOLS_SYSTEM_TEMPLATE = """## Tools
|
| 7 |
+
|
| 8 |
+
You have access to a set of tools you can use to answer the user's question.
|
| 9 |
+
You can invoke functions by writing a "<{dsml_token}function_calls>" block like the following as part of your reply to the user:
|
| 10 |
+
<{dsml_token}function_calls>
|
| 11 |
+
<{dsml_token}invoke name="$FUNCTION_NAME">
|
| 12 |
+
<{dsml_token}parameter name="$PARAMETER_NAME" string="true|false">$PARAMETER_VALUE</{dsml_token}parameter>
|
| 13 |
+
...
|
| 14 |
+
</{dsml_token}invoke>
|
| 15 |
+
<{dsml_token}invoke name="$FUNCTION_NAME2">
|
| 16 |
+
...
|
| 17 |
+
</{dsml_token}invoke>
|
| 18 |
+
</{dsml_token}function_calls>
|
| 19 |
+
|
| 20 |
+
String and scalar parameters should be specified as is without any escaping or quotes, while lists and objects should use JSON format. The "string" attribute should be set to "true" for string type parameters and "false" for other types (numbers, booleans, arrays, objects).
|
| 21 |
+
|
| 22 |
+
If the thinking_mode is enabled, then after function results you should strongly consider outputting a thinking block. Here is an example:
|
| 23 |
+
|
| 24 |
+
<{dsml_token}function_calls>
|
| 25 |
+
...
|
| 26 |
+
</{dsml_token}function_calls>
|
| 27 |
+
|
| 28 |
+
<function_results>
|
| 29 |
+
...
|
| 30 |
+
</function_results>
|
| 31 |
+
|
| 32 |
+
{thinking_start_token}...thinking about results{thinking_end_token}
|
| 33 |
+
|
| 34 |
+
Here are the functions available in JSONSchema format:
|
| 35 |
+
<functions>
|
| 36 |
+
{tool_schemas}
|
| 37 |
+
</functions>
|
| 38 |
+
"""
|
| 39 |
+
|
| 40 |
+
bos_token: str = "<|begin▁of▁sentence|>"
|
| 41 |
+
eos_token: str = "<|end▁of▁sentence|>"
|
| 42 |
+
thinking_start_token: str = "<think>"
|
| 43 |
+
thinking_end_token: str = "</think>"
|
| 44 |
+
dsml_token: str = "|DSML|"
|
| 45 |
+
system_msg_template: str = "{content}"
|
| 46 |
+
user_msg_template: str = "<|User|>{content}<|Assistant|>"
|
| 47 |
+
assistant_msg_template: str = "{reasoning}{content}{tool_calls}<|end▁of▁sentence|>"
|
| 48 |
+
thinking_template = "{reasoning_content}"
|
| 49 |
+
|
| 50 |
+
response_format_template: str = (
|
| 51 |
+
"## Response Format:\n\nYou MUST strictly adhere to the following schema to reply:\n{schema}"
|
| 52 |
+
)
|
| 53 |
+
tool_call_template: str = (
|
| 54 |
+
"<{dsml_token}invoke name=\"{name}\">\n{arguments}\n</{dsml_token}invoke>"
|
| 55 |
+
)
|
| 56 |
+
tool_calls_template = (
|
| 57 |
+
"<{dsml_token}function_calls>\n{tool_calls}\n</{dsml_token}function_calls>"
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
tool_output_template: str = (
|
| 61 |
+
"\n<result>{content}</result>"
|
| 62 |
+
)
|
| 63 |
+
|
| 64 |
+
def to_json(value: Any) -> str:
|
| 65 |
+
try:
|
| 66 |
+
return json.dumps(value, ensure_ascii=False)
|
| 67 |
+
except:
|
| 68 |
+
return json.dumps(value, ensure_ascii=True)
|
| 69 |
+
|
| 70 |
+
def tools_from_openai_format(tools):
|
| 71 |
+
return [tool["function"] for tool in tools]
|
| 72 |
+
|
| 73 |
+
def tool_calls_from_openai_format(tool_calls):
|
| 74 |
+
return [
|
| 75 |
+
{
|
| 76 |
+
"name": tool_call["function"]["name"],
|
| 77 |
+
"arguments": tool_call["function"]["arguments"],
|
| 78 |
+
}
|
| 79 |
+
for tool_call in tool_calls
|
| 80 |
+
]
|
| 81 |
+
|
| 82 |
+
def tool_calls_to_openai_format(tool_calls):
|
| 83 |
+
return [
|
| 84 |
+
{
|
| 85 |
+
"type": "function",
|
| 86 |
+
"function": {
|
| 87 |
+
"name": tool_call["name"],
|
| 88 |
+
"arguments": tool_call["arguments"],
|
| 89 |
+
}
|
| 90 |
+
}
|
| 91 |
+
for tool_call in tool_calls
|
| 92 |
+
]
|
| 93 |
+
|
| 94 |
+
def encode_arguments_to_dsml(tool_call: Dict[str, str]) -> str:
|
| 95 |
+
p_dsml_template = """<{dsml_token}parameter name="{key}" string="{is_str}">{value}</{dsml_token}parameter>"""
|
| 96 |
+
P_dsml_strs = []
|
| 97 |
+
|
| 98 |
+
arguments = json.loads(tool_call["arguments"])
|
| 99 |
+
|
| 100 |
+
for k, v in arguments.items():
|
| 101 |
+
p_dsml_str = p_dsml_template.format(
|
| 102 |
+
dsml_token=dsml_token,
|
| 103 |
+
key=k,
|
| 104 |
+
is_str="true" if isinstance(v, str) else "false",
|
| 105 |
+
value=v if isinstance(v, str) else to_json(v),
|
| 106 |
+
)
|
| 107 |
+
|
| 108 |
+
P_dsml_strs.append(p_dsml_str)
|
| 109 |
+
|
| 110 |
+
return "\n".join(P_dsml_strs)
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def decode_dsml_to_arguments(tool_name: str, tool_args: Dict[str, Tuple[str, str]]) -> Dict[str, str]:
|
| 114 |
+
def _decode_value(key: str, value: str, string: str):
|
| 115 |
+
if string == "true":
|
| 116 |
+
value = to_json(value)
|
| 117 |
+
return f"{to_json(key)}: {value}"
|
| 118 |
+
|
| 119 |
+
tool_args_json = "{" + ", ".join([_decode_value(k, v, string=is_str) for k, (v, is_str) in tool_args.items()]) + "}"
|
| 120 |
+
return dict(name=tool_name, arguments=tool_args_json)
|
| 121 |
+
|
| 122 |
+
def render_tools(tools: List[Dict[str, Union[str, Dict[str, Any]]]]) -> str:
|
| 123 |
+
tools_json = [to_json(t) for t in tools]
|
| 124 |
+
|
| 125 |
+
return TOOLS_SYSTEM_TEMPLATE.format(
|
| 126 |
+
tool_schemas="\n".join(tools_json),
|
| 127 |
+
dsml_token=dsml_token,
|
| 128 |
+
thinking_start_token=thinking_start_token,
|
| 129 |
+
thinking_end_token=thinking_end_token,
|
| 130 |
+
)
|
| 131 |
+
|
| 132 |
+
def find_last_user_index(messages: List[Dict[str, Any]]) -> int:
|
| 133 |
+
last_user_index = -1
|
| 134 |
+
for idx in range(len(messages)-1, -1, -1):
|
| 135 |
+
if messages[idx].get("role") in ["user", "developer"]:
|
| 136 |
+
last_user_index = idx
|
| 137 |
+
break
|
| 138 |
+
return last_user_index
|
| 139 |
+
|
| 140 |
+
def render_message(index: int, messages: List[Dict[str, Any]], thinking_mode: str) -> str:
|
| 141 |
+
assert 0 <= index < len(messages)
|
| 142 |
+
assert thinking_mode in ["chat", "thinking"], f"Invalid thinking_mode `{thinking_mode}`"
|
| 143 |
+
|
| 144 |
+
prompt = ""
|
| 145 |
+
msg = messages[index]
|
| 146 |
+
last_user_idx = find_last_user_index(messages)
|
| 147 |
+
|
| 148 |
+
role = msg.get("role")
|
| 149 |
+
content = msg.get("content")
|
| 150 |
+
tools = msg.get("tools")
|
| 151 |
+
response_format = msg.get("response_format")
|
| 152 |
+
tool_calls = msg.get("tool_calls")
|
| 153 |
+
reasoning_content = msg.get("reasoning_content")
|
| 154 |
+
|
| 155 |
+
if tools:
|
| 156 |
+
tools = tools_from_openai_format(tools)
|
| 157 |
+
if tool_calls:
|
| 158 |
+
tool_calls = tool_calls_from_openai_format(tool_calls)
|
| 159 |
+
|
| 160 |
+
if role == "system":
|
| 161 |
+
prompt += system_msg_template.format(content=content or "")
|
| 162 |
+
if tools:
|
| 163 |
+
prompt += "\n\n" + render_tools(tools)
|
| 164 |
+
|
| 165 |
+
if response_format:
|
| 166 |
+
prompt += "\n\n" + response_format_template.format(schema=to_json(response_format))
|
| 167 |
+
|
| 168 |
+
elif role == "developer":
|
| 169 |
+
assert content, f"Invalid message for role `{role}`: {msg}"
|
| 170 |
+
content_developer = ""
|
| 171 |
+
if tools:
|
| 172 |
+
content_developer += "\n\n" + render_tools(tools)
|
| 173 |
+
|
| 174 |
+
if response_format:
|
| 175 |
+
content_developer += "\n\n" + response_format_template.format(schema=to_json(response_format))
|
| 176 |
+
|
| 177 |
+
content_developer += "\n\n# The user's message is: {}".format(content)
|
| 178 |
+
|
| 179 |
+
prompt += user_msg_template.format(content=content_developer)
|
| 180 |
+
if index == last_user_idx and thinking_mode == "thinking":
|
| 181 |
+
prompt += thinking_start_token
|
| 182 |
+
else:
|
| 183 |
+
prompt += thinking_end_token
|
| 184 |
+
|
| 185 |
+
elif role == "user":
|
| 186 |
+
prompt += user_msg_template.format(content=content)
|
| 187 |
+
|
| 188 |
+
if index == last_user_idx and thinking_mode == "thinking":
|
| 189 |
+
prompt += thinking_start_token
|
| 190 |
+
else:
|
| 191 |
+
prompt += thinking_end_token
|
| 192 |
+
|
| 193 |
+
elif role == "tool":
|
| 194 |
+
prev_assistant_idx = index - 1
|
| 195 |
+
assistant_msg = messages[prev_assistant_idx]
|
| 196 |
+
while prev_assistant_idx >= 0 and assistant_msg.get("role") == "tool":
|
| 197 |
+
prev_assistant_idx -= 1
|
| 198 |
+
assistant_msg = messages[prev_assistant_idx]
|
| 199 |
+
|
| 200 |
+
assert index == 0 or prev_assistant_idx >= 0 and assistant_msg.get("role") == "assistant", f"Invalid messages at {index}:\n{assistant_msg}"
|
| 201 |
+
|
| 202 |
+
tool_call_order = index - prev_assistant_idx
|
| 203 |
+
assistant_tool_calls = assistant_msg.get("tool_calls")
|
| 204 |
+
assert assistant_tool_calls and len(assistant_tool_calls) >= tool_call_order, "No tool calls but found tool output"
|
| 205 |
+
|
| 206 |
+
if tool_call_order == 1:
|
| 207 |
+
prompt += "\n\n<function_results>"
|
| 208 |
+
|
| 209 |
+
prompt += tool_output_template.format(content=content)
|
| 210 |
+
|
| 211 |
+
if tool_call_order == len(assistant_tool_calls):
|
| 212 |
+
prompt += "\n</function_results>"
|
| 213 |
+
|
| 214 |
+
if index >= last_user_idx and thinking_mode == "thinking":
|
| 215 |
+
prompt += "\n\n" + thinking_start_token
|
| 216 |
+
else:
|
| 217 |
+
prompt += "\n\n" + thinking_end_token
|
| 218 |
+
|
| 219 |
+
elif role == "assistant":
|
| 220 |
+
prev_assistant_idx = index
|
| 221 |
+
thinking_part = ""
|
| 222 |
+
|
| 223 |
+
tool_calls_content = ""
|
| 224 |
+
if tool_calls:
|
| 225 |
+
tool_calls = [
|
| 226 |
+
tool_call_template.format(
|
| 227 |
+
dsml_token=dsml_token,
|
| 228 |
+
name=tool_call.get("name"),
|
| 229 |
+
arguments=encode_arguments_to_dsml(tool_call)
|
| 230 |
+
)
|
| 231 |
+
for tool_call in tool_calls
|
| 232 |
+
]
|
| 233 |
+
tool_calls_content += "\n\n" + tool_calls_template.format(
|
| 234 |
+
dsml_token=dsml_token,
|
| 235 |
+
tool_calls="\n".join(tool_calls)
|
| 236 |
+
)
|
| 237 |
+
|
| 238 |
+
summary_content = content or ""
|
| 239 |
+
|
| 240 |
+
if thinking_mode == "thinking" and index > last_user_idx:
|
| 241 |
+
assert reasoning_content or tool_calls, f"ThinkingMode: {thinking_mode}, invalid message without reasoning_content/tool_calls `{msg}` after last user message"
|
| 242 |
+
thinking_part = thinking_template.format(reasoning_content=reasoning_content or "") + thinking_end_token
|
| 243 |
+
|
| 244 |
+
prompt += assistant_msg_template.format(
|
| 245 |
+
reasoning=thinking_part,
|
| 246 |
+
content=summary_content,
|
| 247 |
+
tool_calls=tool_calls_content,
|
| 248 |
+
)
|
| 249 |
+
else:
|
| 250 |
+
raise NotImplementedError(f"Unknown role: {role}")
|
| 251 |
+
|
| 252 |
+
return prompt
|
| 253 |
+
|
| 254 |
+
def drop_thinking_messages(messages: List[Dict[str, Any]], last_user_idx: Optional[int]=None) -> List[Dict[str, Any]]:
|
| 255 |
+
messages_wo_thinking: List[Dict[str, Any]] = []
|
| 256 |
+
last_user_idx = find_last_user_index(messages) if last_user_idx is None else last_user_idx
|
| 257 |
+
for idx, msg in enumerate(messages):
|
| 258 |
+
role = msg.get("role")
|
| 259 |
+
if role in ["user", "system", "tool"] or idx >= last_user_idx:
|
| 260 |
+
messages_wo_thinking.append(msg)
|
| 261 |
+
continue
|
| 262 |
+
|
| 263 |
+
elif role == "assistant":
|
| 264 |
+
msg_wo_thinking = copy.copy(msg)
|
| 265 |
+
msg_wo_thinking.pop("reasoning_content", None)
|
| 266 |
+
messages_wo_thinking.append(msg_wo_thinking)
|
| 267 |
+
|
| 268 |
+
return messages_wo_thinking
|
| 269 |
+
|
| 270 |
+
def encode_messages(messages: List[Dict[str, Any]], thinking_mode: str, context: Optional[List[Dict[str, Any]]] = None, drop_thinking: bool = True, add_default_bos_token: bool = True) -> str:
|
| 271 |
+
context = context if context else []
|
| 272 |
+
full_messages = context + messages
|
| 273 |
+
|
| 274 |
+
prompt = bos_token if add_default_bos_token and len(context) == 0 else ""
|
| 275 |
+
|
| 276 |
+
if thinking_mode == "thinking" and drop_thinking:
|
| 277 |
+
full_messages = drop_thinking_messages(full_messages)
|
| 278 |
+
|
| 279 |
+
for idx in range(len(messages)):
|
| 280 |
+
prompt += render_message(idx + len(context), full_messages, thinking_mode=thinking_mode)
|
| 281 |
+
|
| 282 |
+
return prompt
|
| 283 |
+
|
| 284 |
+
def _read_until_stop(index: int, text: str, stop: List[str]) -> Tuple[int, str, Optional[str]]:
|
| 285 |
+
min_pos = len(text)
|
| 286 |
+
matched_stop = None
|
| 287 |
+
|
| 288 |
+
for s in stop:
|
| 289 |
+
pos = text.find(s, index)
|
| 290 |
+
if pos != -1 and pos < min_pos:
|
| 291 |
+
min_pos = pos
|
| 292 |
+
matched_stop = s
|
| 293 |
+
|
| 294 |
+
if matched_stop:
|
| 295 |
+
content = text[index:min_pos]
|
| 296 |
+
return min_pos + len(matched_stop), content, matched_stop
|
| 297 |
+
else:
|
| 298 |
+
content = text[index:]
|
| 299 |
+
return len(text), content, None
|
| 300 |
+
|
| 301 |
+
def parse_tool_calls(index: int, text: str):
|
| 302 |
+
tool_calls: List[Dict[str, Any]] = []
|
| 303 |
+
stop_token = None
|
| 304 |
+
tool_calls_end_token = f"</{dsml_token}function_calls>"
|
| 305 |
+
|
| 306 |
+
while index < len(text):
|
| 307 |
+
index, _, stop_token = _read_until_stop(index, text, [f"<{dsml_token}invoke", tool_calls_end_token])
|
| 308 |
+
assert _ == ">\n", "Tool call format error"
|
| 309 |
+
|
| 310 |
+
if stop_token == tool_calls_end_token:
|
| 311 |
+
break
|
| 312 |
+
|
| 313 |
+
assert stop_token is not None, "Missing special token"
|
| 314 |
+
|
| 315 |
+
index, tool_name_content, stop_token = _read_until_stop(index, text, [f"<{dsml_token}parameter", f"</{dsml_token}invoke"])
|
| 316 |
+
|
| 317 |
+
p_tool_name = re.findall(r'^\s*name="(.*?)">\n$', tool_name_content, flags=re.DOTALL)
|
| 318 |
+
assert len(p_tool_name) == 1, "Tool name format error"
|
| 319 |
+
tool_name = p_tool_name[0]
|
| 320 |
+
|
| 321 |
+
tool_args: Dict[str, Tuple[str, str]] = {}
|
| 322 |
+
while stop_token == f"<{dsml_token}parameter":
|
| 323 |
+
index, param_content, stop_token = _read_until_stop(index, text, [f"/{dsml_token}parameter"])
|
| 324 |
+
|
| 325 |
+
param_kv = re.findall(r'^ name="(.*?)" string="(true|false)">(.*?)<$', param_content, flags=re.DOTALL)
|
| 326 |
+
assert len(param_kv) == 1, "Parameter format error"
|
| 327 |
+
param_name, string, param_value = param_kv[0]
|
| 328 |
+
|
| 329 |
+
assert param_name not in tool_args, "Duplicate parameter name"
|
| 330 |
+
tool_args[param_name] = (param_value, string)
|
| 331 |
+
|
| 332 |
+
index, content, stop_token = _read_until_stop(index, text, [f"<{dsml_token}parameter", f"</{dsml_token}invoke"])
|
| 333 |
+
assert content == ">\n", "Parameter format error"
|
| 334 |
+
|
| 335 |
+
tool_call = decode_dsml_to_arguments(tool_name=tool_name, tool_args=tool_args)
|
| 336 |
+
tool_calls.append(tool_call)
|
| 337 |
+
|
| 338 |
+
return index, stop_token, tool_calls
|
| 339 |
+
|
| 340 |
+
# NOTE: This function is designed to parse only correctly formatted string and will not attempt to correct malformed output that may be generated by the model.
|
| 341 |
+
def parse_message_from_completion_text(text: str, thinking_mode: str):
|
| 342 |
+
summary_content, reasoning_content, tool_calls = "", "", []
|
| 343 |
+
index, stop_token = 0, None
|
| 344 |
+
tool_calls_start_token = f"\n\n<{dsml_token}function_calls"
|
| 345 |
+
|
| 346 |
+
is_thinking, is_tool_calling = thinking_mode == "thinking", False
|
| 347 |
+
|
| 348 |
+
if is_thinking:
|
| 349 |
+
index, content_delta, stop_token = _read_until_stop(index, text, [thinking_end_token, tool_calls_start_token])
|
| 350 |
+
reasoning_content = content_delta
|
| 351 |
+
assert stop_token == thinking_end_token, "Invalid thinking format"
|
| 352 |
+
|
| 353 |
+
index, content_delta, stop_token = _read_until_stop(index, text, [eos_token, tool_calls_start_token])
|
| 354 |
+
summary_content = content_delta
|
| 355 |
+
if stop_token == tool_calls_start_token:
|
| 356 |
+
is_tool_calling = True
|
| 357 |
+
else:
|
| 358 |
+
assert stop_token == eos_token, "Invalid summary format"
|
| 359 |
+
|
| 360 |
+
if is_tool_calling:
|
| 361 |
+
index, stop_token, tool_calls = parse_tool_calls(index, text)
|
| 362 |
+
|
| 363 |
+
index, tool_ends_text, stop_token = _read_until_stop(index, text, [eos_token])
|
| 364 |
+
assert not tool_ends_text, "Unexpected content after tool calls"
|
| 365 |
+
|
| 366 |
+
assert len(text) == index and stop_token in [eos_token, None], "Unexpected content at end"
|
| 367 |
+
|
| 368 |
+
for sp_token in [bos_token, eos_token, thinking_start_token, thinking_end_token, dsml_token]:
|
| 369 |
+
assert sp_token not in summary_content and sp_token not in reasoning_content, "Unexpected special token in content"
|
| 370 |
+
|
| 371 |
+
return {
|
| 372 |
+
"role": "assistant",
|
| 373 |
+
"content": summary_content,
|
| 374 |
+
"reasoning_content": reasoning_content,
|
| 375 |
+
"tool_calls": tool_calls_to_openai_format(tool_calls)
|
| 376 |
+
}
|
encoding/test_encoding_dsv32.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
import copy
|
| 3 |
+
|
| 4 |
+
from encoding_dsv32 import encode_messages, parse_message_from_completion_text
|
| 5 |
+
|
| 6 |
+
with open("test_input.json", "r") as f:
|
| 7 |
+
test_dict = json.load(f)
|
| 8 |
+
messages = test_dict["messages"]
|
| 9 |
+
messages[0]["tools"] = test_dict["tools"]
|
| 10 |
+
|
| 11 |
+
with open("test_output.txt", "r") as f:
|
| 12 |
+
gold_prompt = f.read().strip()
|
| 13 |
+
|
| 14 |
+
print(messages)
|
| 15 |
+
print("=" * 60)
|
| 16 |
+
|
| 17 |
+
encode_config = dict(thinking_mode="thinking", drop_thinking=True, add_default_bos_token=True)
|
| 18 |
+
prompt = encode_messages(messages, **encode_config)
|
| 19 |
+
print(prompt)
|
| 20 |
+
assert prompt == gold_prompt
|
| 21 |
+
print("=" * 60)
|
| 22 |
+
|
| 23 |
+
tool_call_message = messages[4]
|
| 24 |
+
tool_call_prompt = encode_messages([tool_call_message], context=messages[:4], **encode_config)
|
| 25 |
+
tool_call_message_wo_id = copy.deepcopy(tool_call_message)
|
| 26 |
+
for tool_call in tool_call_message_wo_id["tool_calls"]:
|
| 27 |
+
tool_call.pop("id")
|
| 28 |
+
parsed_tool_call_message = parse_message_from_completion_text(tool_call_prompt, thinking_mode="thinking")
|
| 29 |
+
parsed_tool_call_message.pop("content")
|
| 30 |
+
assert tool_call_message_wo_id == parsed_tool_call_message
|
| 31 |
+
|
| 32 |
+
thinking_message = messages[-6]
|
| 33 |
+
thinking_prompt = encode_messages([thinking_message], context=messages[:-6], **encode_config)
|
| 34 |
+
parsed_thinking_message = parse_message_from_completion_text(thinking_prompt, thinking_mode="thinking")
|
| 35 |
+
parsed_thinking_message.pop("tool_calls")
|
| 36 |
+
assert thinking_message == parsed_thinking_message
|
| 37 |
+
|
| 38 |
+
with open("test_input_search_wo_date.json", "r") as f:
|
| 39 |
+
search_messages = json.load(f)["messages"]
|
| 40 |
+
|
| 41 |
+
with open("test_output_search_wo_date.txt", "r") as f:
|
| 42 |
+
search_gold_prompt = f.read().strip()
|
| 43 |
+
|
| 44 |
+
search_prompt = encode_messages(search_messages, **encode_config)
|
| 45 |
+
assert search_prompt == search_gold_prompt
|
| 46 |
+
|
| 47 |
+
with open("test_input_search_w_date.json", "r") as f:
|
| 48 |
+
search_messages_w_date = json.load(f)["messages"]
|
| 49 |
+
|
| 50 |
+
with open("test_output_search_w_date.txt", "r") as f:
|
| 51 |
+
search_gold_prompt_w_date = f.read().strip()
|
| 52 |
+
|
| 53 |
+
search_prompt_w_date = encode_messages(search_messages_w_date, **encode_config)
|
| 54 |
+
with open("test_output_search_w_date_2.txt", "w") as f:
|
| 55 |
+
f.write(search_prompt_w_date)
|
| 56 |
+
assert search_prompt_w_date == search_gold_prompt_w_date
|
encoding/test_input.json
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"tools": [
|
| 3 |
+
{
|
| 4 |
+
"type": "function",
|
| 5 |
+
"function": {
|
| 6 |
+
"name": "get_datetime",
|
| 7 |
+
"description": "Get the current date and time",
|
| 8 |
+
"parameters": {
|
| 9 |
+
"type": "object",
|
| 10 |
+
"properties": {
|
| 11 |
+
"timezone": {
|
| 12 |
+
"type": "string",
|
| 13 |
+
"description": "The timezone, e.g. Asia/Shanghai, UTC"
|
| 14 |
+
}
|
| 15 |
+
},
|
| 16 |
+
"required": ["timezone"]
|
| 17 |
+
}
|
| 18 |
+
}
|
| 19 |
+
},
|
| 20 |
+
{
|
| 21 |
+
"type": "function",
|
| 22 |
+
"function": {
|
| 23 |
+
"name": "get_weather",
|
| 24 |
+
"description": "Get the weather for a specific date and location",
|
| 25 |
+
"parameters": {
|
| 26 |
+
"type": "object",
|
| 27 |
+
"properties": {
|
| 28 |
+
"location": {
|
| 29 |
+
"type": "string",
|
| 30 |
+
"description": "The city name, e.g. Beijing, Hangzhou"
|
| 31 |
+
},
|
| 32 |
+
"date": {
|
| 33 |
+
"type": "string",
|
| 34 |
+
"description": "The date in YYYY-MM-DD format"
|
| 35 |
+
}
|
| 36 |
+
},
|
| 37 |
+
"required": ["location", "date"]
|
| 38 |
+
}
|
| 39 |
+
}
|
| 40 |
+
}
|
| 41 |
+
],
|
| 42 |
+
"messages": [
|
| 43 |
+
{
|
| 44 |
+
"role": "system",
|
| 45 |
+
"content": "You are a helpful Assistant."
|
| 46 |
+
},
|
| 47 |
+
{
|
| 48 |
+
"role": "user",
|
| 49 |
+
"content": "明天杭州和北京的天气怎么样?"
|
| 50 |
+
},
|
| 51 |
+
{
|
| 52 |
+
"role": "assistant",
|
| 53 |
+
"reasoning_content": "用户询问明天的天气,我需要先获取当前日期来计算明天的日期📅",
|
| 54 |
+
"tool_calls": [
|
| 55 |
+
{
|
| 56 |
+
"id": "call_xK9mN3pL2qR8vT5wY6hZ1aB4",
|
| 57 |
+
"type": "function",
|
| 58 |
+
"function": {
|
| 59 |
+
"arguments": "{\"timezone\": \"Asia/Shanghai\"}",
|
| 60 |
+
"name": "get_datetime"
|
| 61 |
+
}
|
| 62 |
+
}
|
| 63 |
+
]
|
| 64 |
+
},
|
| 65 |
+
{
|
| 66 |
+
"tool_call_id": "call_xK9mN3pL2qR8vT5wY6hZ1aB4",
|
| 67 |
+
"role": "tool",
|
| 68 |
+
"content": "{\"current_date\": \"2024-01-15\", \"current_time\": \"14:30:00\", \"timezone\": \"Asia/Shanghai\"}"
|
| 69 |
+
},
|
| 70 |
+
{
|
| 71 |
+
"role": "assistant",
|
| 72 |
+
"reasoning_content": "现在知道今天是2024-01-15,明天就是2024-01-16。接下来查询杭州和北京明天的天气🌤️",
|
| 73 |
+
"tool_calls": [
|
| 74 |
+
{
|
| 75 |
+
"id": "call_bN7kR9mX3pQ2wL5vY8jZ4cD6",
|
| 76 |
+
"type": "function",
|
| 77 |
+
"function": {
|
| 78 |
+
"arguments": "{\"location\": \"Hangzhou\", \"date\": \"2024-01-16\"}",
|
| 79 |
+
"name": "get_weather"
|
| 80 |
+
}
|
| 81 |
+
},
|
| 82 |
+
{
|
| 83 |
+
"id": "call_dP9mL7kX5rT4yN3wZ2hV8eF1",
|
| 84 |
+
"type": "function",
|
| 85 |
+
"function": {
|
| 86 |
+
"arguments": "{\"location\": \"Beijing\", \"date\": \"2024-01-16\"}",
|
| 87 |
+
"name": "get_weather"
|
| 88 |
+
}
|
| 89 |
+
}
|
| 90 |
+
]
|
| 91 |
+
},
|
| 92 |
+
{
|
| 93 |
+
"tool_call_id": "call_bN7kR9mX3pQ2wL5vY8jZ4cD6",
|
| 94 |
+
"role": "tool",
|
| 95 |
+
"content": "{\"location\": \"Hangzhou\", \"date\": \"2024-01-16\", \"temperature_high\": \"12\", \"temperature_low\": \"5\", \"weather\": \"多云\", \"humidity\": \"65%\"}"
|
| 96 |
+
},
|
| 97 |
+
{
|
| 98 |
+
"tool_call_id": "call_dP9mL7kX5rT4yN3wZ2hV8eF1",
|
| 99 |
+
"role": "tool",
|
| 100 |
+
"content": "{\"location\": \"Beijing\", \"date\": \"2024-01-16\", \"temperature_high\": \"-2\", \"temperature_low\": \"-8\", \"weather\": \"晴\", \"humidity\": \"30%\"}"
|
| 101 |
+
},
|
| 102 |
+
{
|
| 103 |
+
"role": "assistant",
|
| 104 |
+
"reasoning_content": "已获取两个城市明天的天气信息,现在整理给用户✨",
|
| 105 |
+
"content": "根据查询结果,明天(2024年1月16日)的天气情况如下:\n\n**杭州**:\n- 天气:多云\n- 最高温度:12°C\n- 最低温度:5°C\n- 湿度:65%\n\n**北京**:\n- 天气:晴\n- 最高温度:-2°C\n- 最低温度:-8°C\n- 湿度:30%\n\n杭州明天会比较温暖但有些多云,而北京会很冷但是晴天。建议在北京的朋友要注意保暖!"
|
| 106 |
+
},
|
| 107 |
+
{
|
| 108 |
+
"role": "user",
|
| 109 |
+
"content": "谢谢!那后天呢?"
|
| 110 |
+
},
|
| 111 |
+
{
|
| 112 |
+
"role": "assistant",
|
| 113 |
+
"reasoning_content": "用户现在问后天的天气,后天是2024-01-17,我可以直接查询(因为已知今天日期)🗓️",
|
| 114 |
+
"tool_calls": [
|
| 115 |
+
{
|
| 116 |
+
"id": "call_fR3nK8mV7pL4xT2yW9jB5gH3",
|
| 117 |
+
"type": "function",
|
| 118 |
+
"function": {
|
| 119 |
+
"arguments": "{\"location\": \"Hangzhou\", \"date\": \"2024-01-17\"}",
|
| 120 |
+
"name": "get_weather"
|
| 121 |
+
}
|
| 122 |
+
},
|
| 123 |
+
{
|
| 124 |
+
"id": "call_hT5pN2kY9rV6zL3wX1mD7jK8",
|
| 125 |
+
"type": "function",
|
| 126 |
+
"function": {
|
| 127 |
+
"arguments": "{\"location\": \"Beijing\", \"date\": \"2024-01-17\"}",
|
| 128 |
+
"name": "get_weather"
|
| 129 |
+
}
|
| 130 |
+
}
|
| 131 |
+
]
|
| 132 |
+
},
|
| 133 |
+
{
|
| 134 |
+
"tool_call_id": "call_fR3nK8mV7pL4xT2yW9jB5gH3",
|
| 135 |
+
"role": "tool",
|
| 136 |
+
"content": "{\"location\": \"Hangzhou\", \"date\": \"2024-01-17\", \"temperature_high\": \"15\", \"temperature_low\": \"8\", \"weather\": \"小雨\", \"humidity\": \"80%\"}"
|
| 137 |
+
},
|
| 138 |
+
{
|
| 139 |
+
"tool_call_id": "call_hT5pN2kY9rV6zL3wX1mD7jK8",
|
| 140 |
+
"role": "tool",
|
| 141 |
+
"content": "{\"location\": \"Beijing\", \"date\": \"2024-01-17\", \"temperature_high\": \"0\", \"temperature_low\": \"-6\", \"weather\": \"多云\", \"humidity\": \"45%\"}"
|
| 142 |
+
},
|
| 143 |
+
{
|
| 144 |
+
"role": "assistant",
|
| 145 |
+
"reasoning_content": "获取到后天的天气数据,整理回复给用户📝",
|
| 146 |
+
"content": "后天(2024年1月17日)的天气情况:\n\n**杭州**:\n- 天气:小雨\n- 最高温度:15°C\n- 最低温度:8°C\n- 湿度:80%\n\n**北京**:\n- 天气:多云\n- 最高温度:0°C\n- 最低温度:-6°C\n- 湿度:45%\n\n杭州后天会有小雨,温度略有回升,记得带伞。北京会稍微暖和一点,但依然很冷,请继续做好保暖措施。"
|
| 147 |
+
}
|
| 148 |
+
]
|
| 149 |
+
}
|
encoding/test_input_search_w_date.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
encoding/test_input_search_wo_date.json
ADDED
|
@@ -0,0 +1,533 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"messages": [
|
| 3 |
+
{
|
| 4 |
+
"role": "developer",
|
| 5 |
+
"content": "In a year before 2023, between December 1 and 15 (inclusive), a press release reported that as of the 5th of that month, a country had received a total of 16,201,670 vaccine doses, with 7,583,134 administered. That same year, a company's annual report revealed that its nearly 2.2 million members and supporters contributed over $49 million, with 12% of total revenue coming from contributed services. The following year, the annual report stated that the organization had played a role in rescinding a previous administration’s plan to open most of the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas drilling and that contributed services had decreased by 2% to 10%. Who was the emeritus board member that year? Name only, no titles.",
|
| 6 |
+
"tools": [
|
| 7 |
+
{
|
| 8 |
+
"type": "function",
|
| 9 |
+
"function": {
|
| 10 |
+
"name": "search",
|
| 11 |
+
"description": "Searches for information related to query and displays topn results.",
|
| 12 |
+
"parameters": {
|
| 13 |
+
"type": "object",
|
| 14 |
+
"properties": {
|
| 15 |
+
"query": {
|
| 16 |
+
"type": "string",
|
| 17 |
+
"description": "The search query string"
|
| 18 |
+
},
|
| 19 |
+
"topn": {
|
| 20 |
+
"type": "integer",
|
| 21 |
+
"description": "Number of top results to display",
|
| 22 |
+
"default": 10
|
| 23 |
+
},
|
| 24 |
+
"source": {
|
| 25 |
+
"type": "string",
|
| 26 |
+
"description": "Source to search within",
|
| 27 |
+
"enum": [
|
| 28 |
+
"web",
|
| 29 |
+
"news"
|
| 30 |
+
],
|
| 31 |
+
"default": "web"
|
| 32 |
+
}
|
| 33 |
+
},
|
| 34 |
+
"required": [
|
| 35 |
+
"query"
|
| 36 |
+
],
|
| 37 |
+
"additionalProperties": false,
|
| 38 |
+
"$schema": "http://json-schema.org/draft-07/schema#"
|
| 39 |
+
}
|
| 40 |
+
}
|
| 41 |
+
},
|
| 42 |
+
{
|
| 43 |
+
"type": "function",
|
| 44 |
+
"function": {
|
| 45 |
+
"name": "open",
|
| 46 |
+
"description": "Opens the link id from the page indicated by cursor starting at line number loc, showing num_lines lines. Valid link ids are displayed with the formatting: 【{id}†.*】. If cursor is not provided, the most recent page is implied. If id is a string, it is treated as a fully qualified URL associated with source. If loc is not provided, the viewport will be positioned at the beginning of the document or centered on the most relevant passage, if available. Use this function without id to scroll to a new location of an opened page.",
|
| 47 |
+
"parameters": {
|
| 48 |
+
"type": "object",
|
| 49 |
+
"properties": {
|
| 50 |
+
"id": {
|
| 51 |
+
"description": "Link ID (number) or fully qualified URL (string)",
|
| 52 |
+
"anyOf": [
|
| 53 |
+
{
|
| 54 |
+
"type": "integer"
|
| 55 |
+
},
|
| 56 |
+
{
|
| 57 |
+
"type": "string"
|
| 58 |
+
}
|
| 59 |
+
],
|
| 60 |
+
"default": -1
|
| 61 |
+
},
|
| 62 |
+
"cursor": {
|
| 63 |
+
"type": "integer",
|
| 64 |
+
"description": "Page cursor indicator",
|
| 65 |
+
"default": -1
|
| 66 |
+
},
|
| 67 |
+
"loc": {
|
| 68 |
+
"type": "integer",
|
| 69 |
+
"description": "Starting line number",
|
| 70 |
+
"default": -1
|
| 71 |
+
},
|
| 72 |
+
"num_lines": {
|
| 73 |
+
"type": "integer",
|
| 74 |
+
"description": "Number of lines to show",
|
| 75 |
+
"default": -1
|
| 76 |
+
},
|
| 77 |
+
"view_source": {
|
| 78 |
+
"type": "boolean",
|
| 79 |
+
"description": "Whether to view source",
|
| 80 |
+
"default": false
|
| 81 |
+
},
|
| 82 |
+
"source": {
|
| 83 |
+
"type": "string",
|
| 84 |
+
"description": "Source associated with the URL",
|
| 85 |
+
"enum": [
|
| 86 |
+
"web",
|
| 87 |
+
"news"
|
| 88 |
+
],
|
| 89 |
+
"default": "web"
|
| 90 |
+
}
|
| 91 |
+
},
|
| 92 |
+
"additionalProperties": false,
|
| 93 |
+
"$schema": "http://json-schema.org/draft-07/schema#"
|
| 94 |
+
}
|
| 95 |
+
}
|
| 96 |
+
},
|
| 97 |
+
{
|
| 98 |
+
"type": "function",
|
| 99 |
+
"function": {
|
| 100 |
+
"name": "find",
|
| 101 |
+
"description": "Finds exact matches of pattern in the current page, or the page given by cursor.",
|
| 102 |
+
"parameters": {
|
| 103 |
+
"type": "object",
|
| 104 |
+
"properties": {
|
| 105 |
+
"pattern": {
|
| 106 |
+
"type": "string",
|
| 107 |
+
"description": "The exact pattern to search for"
|
| 108 |
+
},
|
| 109 |
+
"cursor": {
|
| 110 |
+
"type": "integer",
|
| 111 |
+
"description": "Page cursor to search in",
|
| 112 |
+
"default": -1
|
| 113 |
+
}
|
| 114 |
+
},
|
| 115 |
+
"required": [
|
| 116 |
+
"pattern"
|
| 117 |
+
],
|
| 118 |
+
"additionalProperties": false,
|
| 119 |
+
"$schema": "http://json-schema.org/draft-07/schema#"
|
| 120 |
+
}
|
| 121 |
+
}
|
| 122 |
+
},
|
| 123 |
+
{
|
| 124 |
+
"type": "function",
|
| 125 |
+
"function": {
|
| 126 |
+
"name": "python",
|
| 127 |
+
"description": "Use this tool to execute Python code. The code will not be shown to the user. This tool should be used for internal reasoning, but not for code that is intended to be visible to the user (e.g. when creating plots, tables, or files). When you send a message containing Python code to python, it will be executed in a stateful Jupyter notebook environment. python will respond with the output of the execution or time out after 120.0 seconds.",
|
| 128 |
+
"parameters": {
|
| 129 |
+
"type": "object",
|
| 130 |
+
"properties": {
|
| 131 |
+
"code": {
|
| 132 |
+
"type": "string",
|
| 133 |
+
"description": "The python code to execute in the jupyter environment."
|
| 134 |
+
}
|
| 135 |
+
},
|
| 136 |
+
"required": [
|
| 137 |
+
"code"
|
| 138 |
+
],
|
| 139 |
+
"additionalProperties": false,
|
| 140 |
+
"$schema": "http://json-schema.org/draft-07/schema#"
|
| 141 |
+
}
|
| 142 |
+
}
|
| 143 |
+
}
|
| 144 |
+
]
|
| 145 |
+
},
|
| 146 |
+
{
|
| 147 |
+
"role": "assistant",
|
| 148 |
+
"content": "",
|
| 149 |
+
"reasoning_content": "The user asks: \"In a year before 2023, between December 1 and 15 (inclusive), a press release reported that as of the 5th of that month, a country had received a total of 16,201,670 vaccine doses, with 7,583,134 administered. That same year, a company's annual report revealed that its nearly 2.2 million members and supporters contributed over $49 million, with 12% of total revenue coming from contributed services. The following year, the annual report stated that the organization had played a role in rescinding a previous administration’s plan to open most of the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas drilling and that contributed services had decreased by 2% to 10%. Who was the emeritus board member that year? Name only, no titles.\"\n\nWe need to parse the puzzle.\n\nWe have clues about a press release about vaccine doses for a country, dated between Dec 1-15 inclusive, reporting as of 5th of that month total doses received 16,201,670 and administered 7,583,134. That is likely a COVID-19 vaccine update for some country. Which country? Might be a smaller country. Could be something like \"Uganda\", \"Zimbabwe\", \"Kenya\", \"Philippines\", etc. Let's search.\n\nSearch for \"16,201,670 vaccine doses\" \"7,583,134 administered\".",
|
| 150 |
+
"tool_calls": [
|
| 151 |
+
{
|
| 152 |
+
"id": null,
|
| 153 |
+
"type": "function",
|
| 154 |
+
"function": {
|
| 155 |
+
"name": "search",
|
| 156 |
+
"arguments": "{\"query\": \"\\\"16,201,670\\\" vaccine doses\", \"topn\": 10, \"source\": \"web\"}"
|
| 157 |
+
}
|
| 158 |
+
}
|
| 159 |
+
]
|
| 160 |
+
},
|
| 161 |
+
{
|
| 162 |
+
"role": "tool",
|
| 163 |
+
"content": "[0] \"16,201,670\" vaccine doses (Search_Results/\"16,201,670\" vaccine doses)\n**viewing lines [0 - 38] of 38**\n\nL0: \nL1: URL: Search_Results/\"16,201,670\" vaccine doses\nL2: # Search Results\nL3: \nL4: * 【0†Kenya's Economy is Showing Resilience as Output Rises ...; publish_date: \nL5: none†www.worldbank.org】 Dec 14, 2021 — As of December 5, 2021, Kenya had \nL6: received a total of 16,201,670 vaccines, with 7,583,134 administered. While \nL7: vaccine acceptance is ...\nL8: * 【1†MINISTRY OF HEALTH; publish_date: none†covidhub.mediacouncil.or.ke】 Dec \nL9: 1, 2021 — Total Doses Received 16,201,670. Table 10 gives the total vaccines \nL10: received since the start of Covid -19 vaccination exercise in the country.\nL11: * 【2†Output Result Page; publish_date: none†open.unicef.org】 ... 16,201,670 \nL12: doses of multiple vaccines nationwide and full vaccination of 15.5 per cent with\nL13: two doses of COVID-19 vaccine as of 31 December 2021.\nL14: * 【3†rebased GDP; publish_date: none†documents1.worldbank.org】 Dec 7, 2021 — \nL15: As of December 5, 2021,. Kenya had received a total of 16,201,670 vaccines, \nL16: with. 7,583,134 administered. Vaccine acceptance is reportedly high.\nL17: * 【4†Integrated Annual Report; publish_date: none†www.co-opbank.co.ke】 May 27,\nL18: 2022 — ... doses of Covid-19 vaccines and administered close to 17 million ... \nL19: 16,201,670, huku 7,583,134 zikiwa tayari zimedungwa watu. Bado kuna ...\nL20: * 【5†World Bank lifts Kenya's growth prospect to 5% in 2021; publish_date: \nL21: none†www.africa-press.net】 ... 16,201,670 vaccines, with 7,583,134 administered.\nL22: While vaccine acceptance is reportedly high there is still a long way to go \nL23: towards the government's ...\nL24: * 【6†2020 Annual Report United States; publish_date: none†www.hi-us.org】 \nL25: including medicine, vaccines, Covid-19 prevention kits, and kits of ... \nL26: 16,201,670. 9,630,584. Prepaid expenses. 56,707. 22,601. Total current assets.\nL27: * 【7†HOSPITAL CENTRAL DE LA DEFENSA; publish_date: \nL28: none†contrataciondelestado.es】 16201670 X. URPA-URPA. 0. HCD-000393/00. KONTRON.\nL29: 7000 ... LASER SHOT LBP-1120. CNEUR-C. NEUROFISIOLOGÍA. 0 ... VICTOREEN CT HEAD\nL30: DOSE PHANTON. 43650-014.\nL31: * 【8†body metal concentrations: Topics by ...; publish_date: \nL32: none†www.science.gov】 PMID:16201670. Design Characteristics and Tobacco Metal \nL33: Concentrations in Filtered Cigars. PubMed. Caruso, Rosalie V; O'Connor, Richard \nL34: J; Travers, Mark J ...\nL35: * 【9†Public Offices, Personal Demands: Capability in ...; publish_date: \nL36: none†dokumen.pub】 ... (16201670).9 The Institutiones Politicae consists of two \nL37: books. Book one deals with the origin, nature and goal of the commonwealth on \nL38: the one hand, and the ...",
|
| 164 |
+
"tool_call_id": null
|
| 165 |
+
},
|
| 166 |
+
{
|
| 167 |
+
"role": "assistant",
|
| 168 |
+
"content": "",
|
| 169 |
+
"reasoning_content": "Result shows Kenya. So the press release is about Kenya's vaccine doses as of Dec 5, 2021. The press release likely by World Bank or something. The search result shows \"World Bank lifts Kenya's growth prospect...\" maybe a press release dated Dec 14, 2021. But the clue says \"between December 1 and 15 (inclusive), a press release reported that as of the 5th of that month, a country had received a total of 16,201,670 vaccine doses, with 7,583,134 administered.\" That matches Kenya on Dec 5, 2021. So the year is 2021.\n\nNow the next clue: \"That same year, a company's annual report revealed that its nearly 2.2 million members and supporters contributed over $49 million, with 12% of total revenue coming from contributed services.\"\n\nThis sounds like an environmental or conservation organization. \"Nearly 2.2 million members and supporters contributed over $49 million.\" That might be something like \"The Nature Conservancy\", \"World Wildlife Fund\", \"Sierra Club\", \"Environmental Defense Fund\", \"Natural Resources Defense Council\", etc. Let's search.\n\nSearch for \"nearly 2.2 million members and supporters contributed over $49 million\" \"12% of total revenue coming from contributed services\".",
|
| 170 |
+
"tool_calls": [
|
| 171 |
+
{
|
| 172 |
+
"id": null,
|
| 173 |
+
"type": "function",
|
| 174 |
+
"function": {
|
| 175 |
+
"name": "search",
|
| 176 |
+
"arguments": "{\"query\": \"\\\"nearly 2.2 million members\\\" \\\"contributed over $49 million\\\"\", \"topn\": 10, \"source\": \"web\"}"
|
| 177 |
+
}
|
| 178 |
+
}
|
| 179 |
+
]
|
| 180 |
+
},
|
| 181 |
+
{
|
| 182 |
+
"role": "tool",
|
| 183 |
+
"content": "[1] \"nearly 2.2 million members\" \"contributed over $49 million\" (Search_Results/\"nearly 2.2 million members\" \"contributed over $49 million\")\n**viewing lines [0 - 41] of 41**\n\nL0: \nL1: URL: Search_Results/\"nearly 2.2 million members\" \"contributed over $49 million\"\nL2: # Search Results\nL3: \nL4: * 【0†The Global Good Fund, Microsoft and Goodwill join forces ...; \nL5: publish_date: none†globalgoodfund.org】 Sep 28, 2022 — ... more than 2.2 million \nL6: people. They additionally contribute close to $49 billion in local, state and \nL7: federal tax revenues. When COVID hit ...\nL8: * 【1†Almost 22 billion American tax dollars spent to wipe out a ...; \nL9: publish_date: none†www.facebook.com】 US military funding for Israel's war crimes\nL10: in Lebanon and Gaza has now cost US taxpayers over $22 billion. When millions \nL11: struggle to afford the ...\nL12: * 【2†Corporate America has largely abandoned its post-January ...; \nL13: publish_date: none†www.citizensforethics.org】 Jul 29, 2025 — Since the January 6\nL14: insurrection, over 2,000 corporate and industry group PACs have given over $174\nL15: million to members of the Sedition ...\nL16: * 【3†Audit shows millions in questionable taxpayer spending at ...; \nL17: publish_date: none†www.aol.com】 18 hours ago — ... nearly doubled from 1.3 \nL18: million to about 2.2 million. That is more than one in four Washington state \nL19: residents receiving Medicaid, and the ...\nL20: * 【4†Incarceration and Poverty in the United States - AAF; publish_date: \nL21: none†www.americanactionforum.org】 Jun 30, 2020 — The United States currently \nL22: incarcerates 2.2 million people, nearly half of whom are non-violent drug \nL23: offenders, accused people held pre ...\nL24: * 【5†How the NRA Spends Revenue (2023); publish_date: none†paddockpost.com】 \nL25: Apr 25, 2025 — In 2023, the NRA reported total revenue of $176 million (compared\nL26: to $211 million in 2022, $227 million in 2021, $282 million in 2020, $292 ...\nL27: * 【6†NCA Newsroom; publish_date: none†www.ncausa.org】 ... 2.2 million U.S. \nL28: jobs—operating in every U.S. state and territory and contributing nearly $350 \nL29: billion to the U.S. economy every year. For media inquiries ...\nL30: * 【7†The Early Childhood Educator Workforce; publish_date: \nL31: none†cscce.berkeley.edu】 About 2.2 million adults are paid to care for and \nL32: educate more than 9.7 million children between birth and age five in center-\nL33: based and home-based settings.\nL34: * 【8†Bringing Out the Worst in Congress: CRA By the Numbers ...; publish_date:\nL35: none†progressivereform.org】 Jul 14, 2025 — In fact, the top ten recipients (out\nL36: of 25) account for almost $7 million, showing how these contributions are \nL37: targeted and strategic. Real ...\nL38: * 【9†Club 100: Over 100 Americans gave more than $100000 to ...; publish_date:\nL39: none†publicintegrity.org】 Jan 7, 2022 — Through Internet investments during the\nL40: 1990s, he attracted 2.2 million online accounts valued at $174 million. Schwab \nL41: has been a vocal ...",
|
| 184 |
+
"tool_call_id": null
|
| 185 |
+
},
|
| 186 |
+
{
|
| 187 |
+
"role": "assistant",
|
| 188 |
+
"content": "",
|
| 189 |
+
"reasoning_content": "Not that. Try search for \"2.2 million members and supporters contributed over $49 million\".",
|
| 190 |
+
"tool_calls": [
|
| 191 |
+
{
|
| 192 |
+
"id": null,
|
| 193 |
+
"type": "function",
|
| 194 |
+
"function": {
|
| 195 |
+
"name": "search",
|
| 196 |
+
"arguments": "{\"query\": \"\\\"2.2 million members\\\" \\\"contributed over $49\\\"\", \"topn\": 10, \"source\": \"web\"}"
|
| 197 |
+
}
|
| 198 |
+
}
|
| 199 |
+
]
|
| 200 |
+
},
|
| 201 |
+
{
|
| 202 |
+
"role": "tool",
|
| 203 |
+
"content": "[2] \"2.2 million members\" \"contributed over $49\" (Search_Results/\"2.2 million members\" \"contributed over $49\")\n**viewing lines [0 - 2] of 2**\n\nL0: \nL1: URL: Search_Results/\"2.2 million members\" \"contributed over $49\"\nL2: # Search Results",
|
| 204 |
+
"tool_call_id": null
|
| 205 |
+
},
|
| 206 |
+
{
|
| 207 |
+
"role": "assistant",
|
| 208 |
+
"content": "",
|
| 209 |
+
"reasoning_content": "Maybe it's an annual report of a non-profit. Search for \"annual report 2.2 million members contributed $49 million\".",
|
| 210 |
+
"tool_calls": [
|
| 211 |
+
{
|
| 212 |
+
"id": null,
|
| 213 |
+
"type": "function",
|
| 214 |
+
"function": {
|
| 215 |
+
"name": "search",
|
| 216 |
+
"arguments": "{\"query\": \"\\\"2.2 million members\\\" \\\"annual report\\\" $49 million\", \"topn\": 10, \"source\": \"web\"}"
|
| 217 |
+
}
|
| 218 |
+
}
|
| 219 |
+
]
|
| 220 |
+
},
|
| 221 |
+
{
|
| 222 |
+
"role": "tool",
|
| 223 |
+
"content": "[3] \"2.2 million members\" \"annual report\" $49 million (Search_Results/\"2.2 million members\" \"annual report\" $49 million)\n**viewing lines [0 - 36] of 36**\n\nL0: \nL1: URL: Search_Results/\"2.2 million members\" \"annual report\" $49 million\nL2: # Search Results\nL3: \nL4: * 【0†20-F; publish_date: none†www.sec.gov】 ANNUAL REPORT PURSUANT TO SECTION \nL5: ... Our membership grew from 2.1 million members as at December 31, 2023 to 2.2 \nL6: million members as at December 31, 2024.\nL7: * 【1†Oportun Reports Fourth Quarter and Full Year 2023 ...; publish_date: \nL8: none†investor.oportun.com】 Mar 12, 2024 — Oportun (Nasdaq: OPRT) is a mission-\nL9: driven fintech that puts its 2.2 million members' financial goals within reach. \nL10: ... annual report on ...\nL11: * 【2†2 0 21; publish_date: none†www.annualreports.com】 ANNUAL REPORT. 2. 0. \nL12: 21. 2. 0. 21. Page 2. 2. DEFENDERS OF WILDLIFE. 2. 0. 21. 2. 0. 21 ... In 2021, \nL13: Defenders of Wildlife's nearly 2.2 million members and.\nL14: * 【3†Annual report and accounts 2020; publish_date: none†www.3i.com】 \nL15: Disclaimer. The Annual report and accounts have been prepared solely to provide \nL16: information to shareholders. ... 2.2 million members. In December 2019, we sold \nL17: ...\nL18: * 【4†united states securities and exchange commission; publish_date: \nL19: none†s21.q4cdn.com】 Dec 14, 2018 — ☒ ANNUAL REPORT ... approximately 5.7 million\nL20: Members, including approximately 2.2 million Members from the acquisition of \nL21: Best Doctors.\nL22: * 【5†securities and exchange commission; publish_date: none†www.sec.gov】 ... \nL23: Annual Report on Form 10-K filed with the SEC on March 10, 2020. The ... 2.2 \nL24: million members at June 30, 2020. The following table highlights the ...\nL25: * 【6†2022-23 Annual Comprehensive Financial Report - CalPERS; publish_date: \nL26: none†www.calpers.ca.gov】 Nov 17, 2023 — ... annual report is consistent with \nL27: these accounting principles ... 2.2 million members and health benefit services \nL28: to over 1.5 million ...\nL29: * 【7†Medical Centers Report; publish_date: \nL30: none†regents.universityofcalifornia.edu】 Oct 8, 2019 — which will allow its 2.2 \nL31: million members to receive advanced and ... annual report of the University of \nL32: California. For the Medical ...\nL33: * 【8†Working TogeTher to make HealtH care better; publish_date: \nL34: none†www.unitedhealthgroup.com】 Feb 8, 2012 — ANNUAL REPORT PURSUANT TO SECTION \nL35: 13 OR 15(d) OF THE ... approximately 2.2 million members enrolled in its \nL36: Medicare. Advantage ...",
|
| 224 |
+
"tool_call_id": null
|
| 225 |
+
},
|
| 226 |
+
{
|
| 227 |
+
"role": "assistant",
|
| 228 |
+
"content": "",
|
| 229 |
+
"reasoning_content": "Result 2 shows \"Defenders of Wildlife\". That might be the organization. Let's open.",
|
| 230 |
+
"tool_calls": [
|
| 231 |
+
{
|
| 232 |
+
"id": null,
|
| 233 |
+
"type": "function",
|
| 234 |
+
"function": {
|
| 235 |
+
"name": "open",
|
| 236 |
+
"arguments": "{\"cursor\": 3, \"id\": 2}"
|
| 237 |
+
}
|
| 238 |
+
}
|
| 239 |
+
]
|
| 240 |
+
},
|
| 241 |
+
{
|
| 242 |
+
"role": "tool",
|
| 243 |
+
"content": "[4] www.annualreports.com (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2021.pdf)\n**viewing lines [0 - 53] of 261**\n\nL0: \nL1: URL: https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-\nL2: wildlife_2021.pdf\nL3: ===== Page 1 ===== 2021 ANNUAL REPORT ===== Page 2 ===== # DEFENDERS OF WILDLIFE\nL4: made important progress for imperiled species and vital landscapes across the \nL5: United States in 2021. \\--- **LAWYERS** immediately **challenged** the premature\nL6: and reckless decision to strip **gray wolves** of federal **Endangered Species \nL7: Act (ESA)** protections. For many decades, Defenders has led the effort to \nL8: protect and restore the gray wolf, and we will continue to fight the \nL9: unscientific and hostile anti-wolf policies that impede conservation progress \nL10: and will carry on our unrelenting battle to restore federal protections for this\nL11: iconic keystone species. \\--- **LOBBYISTS** worked around the clock to keep \nL12: wildlife and climate priorities in the **Infrastructure Investment and Jobs \nL13: Act**. We also continue fighting to keep important wildlife and habitat funding \nL14: in relevant **appropriations bills**. \\--- 2 DEFENDERS OF WILDLIFE ===== Page 3 \nL15: ===== POLICY EXPERTS pushed forward on the urgent need for a National \nL16: Biodiversity Strategy (NBS), an all-of-government approach to address the \nL17: unprecedented loss of wildlife and habitat we are experiencing. We have coupled \nL18: this with our new campaign to expand the National Wildlife Refuge System to \nL19: preserve our nation’s only lands set aside for wildlife. By defending, funding \nL20: and expanding our national wildlife refuges, we will directly address \nL21: biodiversity loss and climate change while promoting increased equitable access \nL22: to nature. FIELD TEAMS were on the ground helping to recover imperiled species. \nL23: From panthers and sea turtles in Florida to wolves, bison and black-footed \nL24: ferrets in Montana, Defenders’ conservation experts were in the field saving \nL25: wildlife all over the country. CONSERVATION INNOVATION EXPERTS provided \nL26: comprehensive analyses to guide policy and inform conservation strategies to \nL27: reach the goal of protecting 30% of our terrestrial and marine systems by 2030 \nL28: (“30x30”). Defenders’ Center for Conservation Innovation (CCI) produced a report\nL29: which details actions we need to take to achieve 30x30 while protecting \nL30: biodiversity and addressing the climate crisis. DEFENDERS.ORG ===== Page 4 =====\nL31: WE HAVE ACCOMPLISHED MUCH THIS YEAR WORKING WITH AN ADMINISTRATION THAT VALUES \nL32: SCIENCE AND CONSERVATION. Our many successes include the return of protections \nL33: to the Tongass National Forest in Alaska and the suspension of oil and gas \nL34: leasing permits for the Arctic National Wildlife Refuge. Defenders also played a\nL35: lead role in successfully defending the Migratory Bird Protection Act from \nL36: attack and securing critical protections for migratory birds. Throughout 2021 \nL37: Defenders made important progress for the wildlife and wild places we all love, \nL38: yet our nation’s wildlife still face unprecedented challenges. More and more \nL39: species, including manatees, Mexican gray wolves, polar bears and North Atlantic\nL40: right whales, face the very real threat of extinction because of climate \nL41: change, habitat loss, pollution and inadequate protections. In our work we \nL42: continue to demonstrate success by following the science, building partnerships,\nL43: leading with innovative solutions and focusing on collaborative and practical \nL44: approaches in defense of nature. Together we can make a lasting difference for \nL45: wildlife and habitats. Your support is essential to our work and we couldn’t do \nL46: it without you. Thank you for being an important part of our efforts to protect \nL47: imperiled wildlife across our nation. Jamie Rappaport Clark President and CEO \nL48: John Dayton Board Chair OUR NEW TELEVISION SERIES, WILDLIFE NATION WITH JEFF \nL49: CORWIN, premiered in October and airs every weekend on ABC stations nationwide. \nL50: This groundbreaking series takes Jeff across the country to meet Defenders’ \nL51: experts along with our science, tribal and community partners to educate and \nL52: inspire viewers to join with Defenders to protect wildlife. While highlighting \nL53: some of our important conservation work and raising awareness of important ",
|
| 244 |
+
"tool_call_id": null
|
| 245 |
+
},
|
| 246 |
+
{
|
| 247 |
+
"role": "assistant",
|
| 248 |
+
"content": "",
|
| 249 |
+
"reasoning_content": "Search within PDF for \"2.2 million members\".",
|
| 250 |
+
"tool_calls": [
|
| 251 |
+
{
|
| 252 |
+
"id": null,
|
| 253 |
+
"type": "function",
|
| 254 |
+
"function": {
|
| 255 |
+
"name": "find",
|
| 256 |
+
"arguments": "{\"cursor\": 4, \"pattern\": \"2.2\"}"
|
| 257 |
+
}
|
| 258 |
+
}
|
| 259 |
+
]
|
| 260 |
+
},
|
| 261 |
+
{
|
| 262 |
+
"role": "tool",
|
| 263 |
+
"content": "[5] Find results for text: `2.2` in `www.annualreports.com` (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2021.pdf/find?pattern=2.2)\n**viewing lines [0 - 4] of 4**\n\nL0: # 【0†match at L187】\nL1: 2021, Defenders of Wildlife’s nearly 2.2 million members and supporters \nL2: contributed more than $49 million for wildlife and wildlife habitat. This figure\nL3: includes all those who generously donated their time and expertise. The \nL4: steadfast support of our donors allows Defenders to sustain our program and ",
|
| 264 |
+
"tool_call_id": null
|
| 265 |
+
},
|
| 266 |
+
{
|
| 267 |
+
"role": "assistant",
|
| 268 |
+
"content": "",
|
| 269 |
+
"reasoning_content": "Open around L180.",
|
| 270 |
+
"tool_calls": [
|
| 271 |
+
{
|
| 272 |
+
"id": null,
|
| 273 |
+
"type": "function",
|
| 274 |
+
"function": {
|
| 275 |
+
"name": "open",
|
| 276 |
+
"arguments": "{\"cursor\": 4, \"loc\": 170}"
|
| 277 |
+
}
|
| 278 |
+
}
|
| 279 |
+
]
|
| 280 |
+
},
|
| 281 |
+
{
|
| 282 |
+
"role": "tool",
|
| 283 |
+
"content": "[6] www.annualreports.com (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2021.pdf)\n**viewing lines [170 - 215] of 261**\n\nL170: into the wild. **10 DEFENDERS OF WILDLIFE** ===== Page 11 ===== AFTER ANOTHER \nL171: SUCCESSFUL DEFENDERS LAWSUIT ON BEHALF OF THE CRITICALLY ENDANGERED RED WOLF, \nL172: FWS reversed its decision to limit the recovery area and committed to a robust \nL173: release strategy. After years of inaction, FWS released eight wolves to the wild\nL174: in North Carolina and plan to release nine more wolves in the spring of 2022. \nL175: This is an incredible win for this critically endangered species whose \nL176: population has dwindled down to single digits in the wild because of \nL177: mismanagement, vehicle strikes and poaching. DEFENDERS CONTINUED TO LEAD EFFORTS\nL178: TO PROTECT THE FLORIDA MANATEE, a beloved species that suffered the deadliest \nL179: year on record in 2021, tragically surpassing 1,000 deaths because of water \nL180: pollution and lack of warm water habitat. Defenders led advocacy and education \nL181: aimed at restoring the natural flow of the dammed Ocklawaha River, which would \nL182: provide critical warm-water habitat that manatees need to survive. Defenders’ \nL183: legal team continued to fight for manatees in the courts, holding government \nL184: agencies accountable for protecting critical habitat and addressing the \nL185: devastating water pollution that is killing the seagrass and causing manatees to\nL186: starve. DAVID TES | SAM FRENZY DRAW DEFENDERS.ORG 11 ===== Page 12 ===== In \nL187: 2021, Defenders of Wildlife’s nearly 2.2 million members and supporters \nL188: contributed more than $49 million for wildlife and wildlife habitat. This figure\nL189: includes all those who generously donated their time and expertise. The \nL190: steadfast support of our donors allows Defenders to sustain our program and \nL191: public education efforts in the field, the courts and on Capitol Hill. 2021 \nL192: SOURCES OF FUNDS Grants and contributions $29,057 Bequests, trusts and split \nL193: interests $7,692 Income from investments, annuity reserve funds and trusts \nL194: $3,354 Royalties and other income $3,576 Contributed services $6,140 Total \nL195: Revenue $49,819 USES OF FUNDS Biodiversity conservation $22,420 Constituency \nL196: mobilization $16,324 Fundraising $1,211 Management and general $5,865 Total \nL197: Expenses $45,820 Change in net assets $3,999 Net assets, start of year $41,145 \nL198: Net Assets, End of the Year $45,144 Dollars are in thousands. 12 DEFENDERS OF \nL199: WILDLIFE Grants and contributions 58% Income from investments 7% Requests, \nL200: trusts and split interests 15% Royalties and other income 7% Contributed \nL201: services 12% Program and support services 97% Fundraising 3% ===== Page 13 =====\nL202: DEFENDERS.ORG 13 ===== Page 14 ===== John Dayton, Esq.* Chair Texas Sheryl \nL203: Sachs* Vice Chair Connecticut Whitfield Bailey* Secretary Tennessee Mark Caylor*\nL204: Treasurer District of Columbia Sylvia Baca* California Donald Barry, Esq. \nL205: Oregon Dinah Bear, Esq. Arizona Kim O’Keefe Beck, Ph.D California Gabriela \nL206: Chavarria, Ph.D Washington Jamie Rappaport Clark* President & CEO Virginia \nL207: Caroline D. Gabel Maryland Keith M. Harper, Esq. Maryland John Donovan, Esq. \nL208: Montana and California James M. Hecker, Esq. Virginia Judith Ponsikoff, Ph.D* \nL209: California Terry L. Root, Ph.D Florida BOARD EMERITUS Terry C. Pelster, Esq. New\nL210: York *Executive Committee member* ST A F F & A D V I S O R S SCIENCE ADVISORS \nL211: Gabriela Chavarria, Ph.D Burke Museum, University of Washington Leah Gerber, \nL212: Ph.D Arizona State University Kathayoon Khalil, Ph.D Oregon Zoo Rurik List, Ph.D\nL213: Universidad Autónoma Metropolitana-Lerma Barry Noon, Ph.D Colorado State \nL214: University Terry L. Root, Ph.D Stanford University Mark Schwartz, Ph.D \nL215: University of California-Davis David S. Wilcox, Ph.D Princeton University Rae ",
|
| 284 |
+
"tool_call_id": null
|
| 285 |
+
},
|
| 286 |
+
{
|
| 287 |
+
"role": "assistant",
|
| 288 |
+
"content": "",
|
| 289 |
+
"reasoning_content": "Scrolling further for \"Contributed services 12%\". Already seen. So the annual report is Defenders of Wildlife 2021 annual report.\n\nNext clue: \"The following year, the annual report stated that the organization had played a role in rescinding a previous administration’s plan to open most of the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas drilling and that contributed services had decreased by 2% to 10%.\"\n\nThus, the following year (2022) annual report of Defenders of Wildlife includes mention of rescinding plan to open most of 22 million acres of NPR-A to oil and gas drilling. Also contributed services decreased to 10% (from 12% in 2021). So we need to find the 2022 annual report for Defenders of Wildlife.\n\nSearch for \"Defenders of Wildlife 2022 annual report National Petroleum Reserve Alaska\".",
|
| 290 |
+
"tool_calls": [
|
| 291 |
+
{
|
| 292 |
+
"id": null,
|
| 293 |
+
"type": "function",
|
| 294 |
+
"function": {
|
| 295 |
+
"name": "search",
|
| 296 |
+
"arguments": "{\"query\": \"Defenders of Wildlife 2022 annual report National Petroleum Reserve Alaska\", \"topn\": 10, \"source\": \"web\"}"
|
| 297 |
+
}
|
| 298 |
+
}
|
| 299 |
+
]
|
| 300 |
+
},
|
| 301 |
+
{
|
| 302 |
+
"role": "tool",
|
| 303 |
+
"content": "[7] Defenders of Wildlife 2022 annual report National Petroleum Reserve Alaska (Search_Results/Defenders of Wildlife 2022 annual report National Petroleum Reserve Alaska)\n**viewing lines [0 - 37] of 37**\n\nL0: \nL1: URL: Search_Results/Defenders of Wildlife 2022 annual report National Petroleum \nL2: Reserve Alaska\nL3: # Search Results\nL4: \nL5: * 【0†CELEBRATING YEARS; publish_date: none†www.annualreports.com】 With less \nL6: than 340 right whales left in the wild, Defenders is fighting tirelessly to end \nL7: deadly lobster gear entanglements and vessel strikes that are driving ...\nL8: * 【1†Financials; publish_date: none†defenders.org】 We invite you to explore \nL9: the reports below to learn more about our activities and accomplishments, and \nL10: how we put your money to work for wildlife.\nL11: * 【2†Alaska Program Looks Back on 2022; publish_date: none†defenders.org】 Feb \nL12: 9, 2023 — Thanks to a lawsuit joined by Defenders, seven million acres were \nL13: returned to protection within the National Petroleum Reserve-Alaska (NPR-A), ...\nL14: * 【3†Defenders-of-Wildlife-2022-Financial-Statement. ...; publish_date: \nL15: none†defenders.org】 We have audited the accompanying consolidated financial \nL16: statements of Defenders of Wildlife and Affiliated Defenders of Wildlife Action \nL17: Fund (collectively, ...\nL18: * 【4†2022 Annual Report; publish_date: none†alaskaconservation.org】 Jun 13, \nL19: 2023 — In 2022, we focused on three landscapes: the Arctic. National Wildlife \nL20: Refuge, Bristol Bay, and the Tongass National Forest. In March 2022,.\nL21: * 【5†Assessment of ecological and cultural values within the ...; \nL22: publish_date: none†www.blm.gov】 This document was written to provide technical \nL23: information regarding the ecological importance of the National Petroleum \nL24: Reserve – Alaska (NPR-A). Several ...\nL25: * 【6†Accomplishments Report; publish_date: none†defenders.org】 National \nL26: Petroleum Reserve-Alaska. Identified for exceptional wildlife and cultural \nL27: values, including critical habitat for polar bears and other species ...\nL28: * 【7†2022 annual report; publish_date: none†dory-\nL29: plantain-s2zc.squarespace.com】 These projects are made possible through \nL30: collaborations with Defenders of. Wildlife, Cook Inletkeeper, Trustees for \nL31: Alaska,. Environmental Investigation Agency, ...\nL32: * 【8†23IMPACT REPORT; publish_date: none†www.annualreports.com】 Defenders of \nL33: Wildlife made incredible progress protecting wildlife and wild places in 2023, \nL34: helping shape a brighter future for imperiled species and vital ...\nL35: * 【9†From Leasing to Land Protections; publish_date: none†defenders-cci.org】 \nL36: Abstract. When you hear the name, National Petroleum Reserve - Alaska (NPR-A, or\nL37: Reserve), you might think of a barren land filled with oil wells and ...",
|
| 304 |
+
"tool_call_id": null
|
| 305 |
+
},
|
| 306 |
+
{
|
| 307 |
+
"role": "assistant",
|
| 308 |
+
"content": "",
|
| 309 |
+
"reasoning_content": "Open result 0.",
|
| 310 |
+
"tool_calls": [
|
| 311 |
+
{
|
| 312 |
+
"id": null,
|
| 313 |
+
"type": "function",
|
| 314 |
+
"function": {
|
| 315 |
+
"name": "open",
|
| 316 |
+
"arguments": "{\"cursor\": 7, \"id\": 0}"
|
| 317 |
+
}
|
| 318 |
+
}
|
| 319 |
+
]
|
| 320 |
+
},
|
| 321 |
+
{
|
| 322 |
+
"role": "tool",
|
| 323 |
+
"content": "[8] www.annualreports.com (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2022.pdf)\n**viewing lines [0 - 53] of 289**\n\nL0: \nL1: URL: https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-\nL2: wildlife_2022.pdf\nL3: ===== Page 1 ===== 2022 Impact Report C E L E B R A T I N G Y E A R S ===== Page\nL4: 2 ===== 2022 Defenders of Wildlife made important progress for imperiled \nL5: species and vital landscapes across the United States in 2022. GRAY WOLF | JIM \nL6: GUMMERAL MAY STOCK PRIOR Lawyers successfully challenged the previous \nL7: administration’s decision to delist the gray wolf and restored critical federal \nL8: protections under the Endangered Species Act. This latest triumph in court is \nL9: part of our ongoing battle to protect and restore gray wolves throughout their \nL10: historical range and shield them from persecution by extremist legislators in \nL11: Idaho, Montana and Wyoming. TWO MORE FATALIZED GRAY SWALLETS TO SEA TO SHARE \nL12: ALLIANCE Lobbyists worked around the clock to expand funding for wildlife \nL13: conservation in the FY2022 federal spending bill, which included $31 million (a \nL14: 44% increase) for the Bureau of Land Management’s Threatened and Endangered \nL15: Species Program, $2.5 million (an 81% increase) for the U.S. Department of \nL16: Agriculture Wildlife Services’ Nonlethal Initiative to prevent human-wildlife \nL17: conflicts and $21 million (a 320% increase) for North Atlantic right whale \nL18: conservation. 2 DEFENDERS OF WILDLIFE ===== Page 3 ===== **Policy Experts** \nL19: played a crucial role in securing international trade protections for 100 \nL20: species of sharks and rays, all 158 species of glass frogs and 73 species of \nL21: reptiles, including 21 species of desert horned lizards, at the Convention on \nL22: International Trade in Endangered Species (CITES) in Panama. \\--- **Field \nL23: Teams** worked tirelessly to protect and restore imperiled species across the \nL24: country. From Florida manatees and red wolves in the Southeast to belugas and \nL25: grizzly bears in Alaska, Defenders’ conservation experts were on the ground \nL26: saving species that need our help to survive and thrive. \\--- **Conservation \nL27: Innovation Experts** published more than 10 peer-reviewed studies on topics that\nL28: include the Cook Inlet beluga whale, golden-cheeked warbler, global parrot \nL29: biodiversity, the Endangered Species Act, the effects of mountaintop removal \nL30: mining on endangered species, the ecological importance of panthers and the \nL31: implementation of “30x30” – the globally recognized goal to which President \nL32: Biden committed the U.S. to conserve 30% of our imperiled lands and waters by \nL33: 2030. \\--- **DEFENDERS.ORG** ===== Page 4 ===== THANK YOU Defenders celebrated \nL34: our 75th anniversary in 2022—an exciting milestone that we attribute to our \nL35: unwavering dedication to our wildlife conservation mission. From helping to pass\nL36: the Endangered Species Act and other bedrock conservation laws to leading the \nL37: advocacy on the reintroduction of wolves to Yellowstone National Park and other \nL38: parts of the West, Defenders is proud to inspire, lead and ultimately celebrate \nL39: some of the most consequential conservation wins for wildlife and wild places. \nL40: It is wonderfully fitting that we also mark 2022 as a year when we successfully \nL41: defended, yet again, the original focal species and symbol of our organization, \nL42: the gray wolf. While the future for gray wolves and many other species remains \nL43: uncertain, we will never stop fighting to protect the imperiled wildlife that \nL44: need us and to restore vibrant and balanced ecosystems. Our mission is more \nL45: important than ever due to the escalating biodiversity and climate crises. \nL46: Defenders is determined to build on our accomplishments and seize new \nL47: opportunities to address these challenges through our multifaceted approach to \nL48: conservation. We focus on developing innovative and science-based solutions, \nL49: coordinating on-the-ground species and habitat restoration, promoting human-\nL50: wildlife coexistence, protecting and strengthening our bedrock environmental \nL51: laws, investing in impactful collaborations and partnerships, building a more \nL52: diverse and powerful conservation movement and challenging attacks on wildlife \nL53: through advocacy, policy and litigation. Defenders’ continued success is made ",
|
| 324 |
+
"tool_call_id": null
|
| 325 |
+
},
|
| 326 |
+
{
|
| 327 |
+
"role": "assistant",
|
| 328 |
+
"content": "",
|
| 329 |
+
"reasoning_content": "Search within PDF for \"National Petroleum Reserve\".",
|
| 330 |
+
"tool_calls": [
|
| 331 |
+
{
|
| 332 |
+
"id": null,
|
| 333 |
+
"type": "function",
|
| 334 |
+
"function": {
|
| 335 |
+
"name": "find",
|
| 336 |
+
"arguments": "{\"cursor\": 8, \"pattern\": \"Petroleum\"}"
|
| 337 |
+
}
|
| 338 |
+
}
|
| 339 |
+
]
|
| 340 |
+
},
|
| 341 |
+
{
|
| 342 |
+
"role": "tool",
|
| 343 |
+
"content": "[9] Find results for text: `petroleum` in `www.annualreports.com` (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2022.pdf/find?pattern=petroleum)\n**viewing lines [0 - 4] of 4**\n\nL0: # 【0†match at L201】\nL1: the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas \nL2: drilling and removed protections for important wildlife habitat. Protections \nL3: have now been restored for nearly half of the reserve’s pristine lands, which \nL4: are vital habitat for shorebirds, denning polar bears and tens of thousands of ",
|
| 344 |
+
"tool_call_id": null
|
| 345 |
+
},
|
| 346 |
+
{
|
| 347 |
+
"role": "assistant",
|
| 348 |
+
"content": "",
|
| 349 |
+
"reasoning_content": "Open around L190.",
|
| 350 |
+
"tool_calls": [
|
| 351 |
+
{
|
| 352 |
+
"id": null,
|
| 353 |
+
"type": "function",
|
| 354 |
+
"function": {
|
| 355 |
+
"name": "open",
|
| 356 |
+
"arguments": "{\"cursor\": 8, \"loc\": 180}"
|
| 357 |
+
}
|
| 358 |
+
}
|
| 359 |
+
]
|
| 360 |
+
},
|
| 361 |
+
{
|
| 362 |
+
"role": "tool",
|
| 363 |
+
"content": "[10] www.annualreports.com (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2022.pdf)\n**viewing lines [180 - 227] of 289**\n\nL180: the sixth successful transfer of bison to the Assiniboine and Sioux Tribes of \nL181: Fort Peck since 2019. \\--- **SWIFT FIX KITS | © ROSIMA PAELARINTSKIMMA MADDIAL \nL182: 200 AND CONSERVATION BIOLOGY INSTITUTE** \\--- **Celebrating our third year** of \nL183: a collaborative program with the Aaniih and Nakoda Tribes and others to restore \nL184: swift foxes to the Fort Belknap Indian Reservation in Montana, Defenders helped \nL185: with the release of 28 more swift foxes. With over 100 foxes reintroduced \nL186: through this program, monitoring efforts show that they are reproducing in the \nL187: wild—a critical measure of success for a self-sustaining population. \\--- \nL188: **Defenders continued to lead the way** for conserving and recovering the \nL189: endangered black-footed ferret, supporting the black-footed ferret survey for \nL190: the Fort Belknap Indian community. Thirty-six ferrets were vaccinated against \nL191: sylvatic plague and two dozen kits were released in the wild. \\--- **10 \nL192: DEFENDERS OF WILDLIFE** ===== Page 11 ===== Defenders helped to bring hope for \nL193: recovery for the endangered military macaw, adding 11 fledglings to a growing \nL194: wild population in Puerta Vallarta, Mexico, that is under pressure from habitat \nL195: loss and poachers for the illegal pet trade. Accord- ing to our recent report, \nL196: the 2008 parrot trade ban that Defenders fought to achieve is working. \nL197: Preventing more than 30,000 parrots from being illegally trapped each year, the \nL198: trade ban has resulted in a 47% decrease in the illegal trade of parrots and an \nL199: 88% decrease in U.S. seizures of Mexican parrots. As a result of a Defenders \nL200: lawsuit, BLM rescinded the previous administration’s plan that opened most of \nL201: the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas \nL202: drilling and removed protections for important wildlife habitat. Protections \nL203: have now been restored for nearly half of the reserve’s pristine lands, which \nL204: are vital habitat for shorebirds, denning polar bears and tens of thousands of \nL205: caribou in the Teshekpuk caribou herd. Our new storymap illustrates why the \nL206: reserve is so important to wildlife. Defenders marked the 20th anniversary of \nL207: our Sea Otter Awareness Week. In celebration of this milestone, we sponsored \nL208: state legislation, signed by Gov. Gavin Newsom, that formally recognizes the \nL209: event’s anniversary and acknowledges the vital role that sea otters play in \nL210: California’s nearshore ecosystems. This annual celebration provides a unique \nL211: opportunity to raise awareness of the important role sea otters play in \nL212: maintaining ecosystem health, our need to coexist with sea otters and the \nL213: efforts of Defenders and others in advancing sea otter conservation. \nL214: DEFENDERS.ORG ===== Page 12 ===== FINANCIAL REPORT In 2022, Defenders of \nL215: Wildlife’s nearly 2.2 million members and supporters contributed more than $41 \nL216: million for wildlife and wildlife habitat. This figure includes all those who \nL217: generously donated their time and expertise. The steadfast support of our donors\nL218: allows Defenders to sustain our program and public education efforts in the \nL219: field, the courts and on Capitol Hill. 2022 SOURCES OF FUNDS Grants and \nL220: contributions $28,946 Bequests, trusts and split interests $13,928 Income from \nL221: investments, annuity reserve funds and trusts (-$7,495) Royalties and other \nL222: income $744 Contributed services $5,047 Total Revenue $41,170 USES OF FUNDS \nL223: Biodiversity conservation $18,970 Constituency mobilization $16,528 Fundraising \nL224: $1,029 Management and general $6,354 Total Expenses $42,881 Change in net assets\nL225: (-$1,711) Net assets, start of year $45,144 Net Assets, End of the Year $43,433\nL226: Dollars are in thousands. 12 DEFENDERS OF WILDLIFE Grants and contributions 59%\nL227: Contributed services 10% Royalties and other income 2% Bequests, trusts and ",
|
| 364 |
+
"tool_call_id": null
|
| 365 |
+
},
|
| 366 |
+
{
|
| 367 |
+
"role": "assistant",
|
| 368 |
+
"content": "",
|
| 369 |
+
"reasoning_content": "Scrolling a bit more for \"Contributed services 10%\". Already seen. So indeed the 2022 annual report shows contributed services 10%, down from 12% in 2021.\n\nThus the organization is Defenders of Wildlife.\n\nThe question: \"Who was the emeritus board member that year? Name only, no titles.\"\n\nWe need to identify the emeritus board member listed in the 2022 annual report. From the 2021 annual report, we saw \"BOARD EMERITUS Terry C. Pelster, Esq.\" However, that is for 2021. The question asks \"Who was the emeritus board member that year?\" That year refers to the following year (2022). So we need to check the 2022 annual report for the emeritus board member.\n\nOpen the 2022 PDF near the board list. Search for \"Emeritus\".",
|
| 370 |
+
"tool_calls": [
|
| 371 |
+
{
|
| 372 |
+
"id": null,
|
| 373 |
+
"type": "function",
|
| 374 |
+
"function": {
|
| 375 |
+
"name": "find",
|
| 376 |
+
"arguments": "{\"cursor\": 8, \"pattern\": \"Emeritus\"}"
|
| 377 |
+
}
|
| 378 |
+
}
|
| 379 |
+
]
|
| 380 |
+
},
|
| 381 |
+
{
|
| 382 |
+
"role": "tool",
|
| 383 |
+
"content": "[11] Find results for text: `emeritus` in `www.annualreports.com` (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2022.pdf/find?pattern=emeritus)\n**viewing lines [0 - 10] of 10**\n\nL0: # 【0†match at L237】\nL1: Sisk, Ph.D British Columbia, Canada BOARD EMERITUS Terry C. Pelster, Esq. New \nL2: York *Executive Committee member* STAFF & ADVISORS SCIENCE ADVISORS Gabriela \nL3: Chavarria, Ph.D Burke Museum, University of Washington Leah Gerber, Ph.D Arizona\nL4: State University Kathayoon Khalil, Ph.D Oregon Zoo Rurik List, Ph.D Universidad\nL5: \nL6: # 【1†match at L243】\nL7: Davis Thomas D. Sisk, Ph.D Emeritus Professor Northern Arizona University David \nL8: S. Wilcox, Ph.D Princeton University Rae Wynn-Grant, Ph.D National Geographic \nL9: Society SENIOR STAFF Jamie Rappaport Clark President & CEO Thu Pham Chief of \nL10: Staff James Stofan Senior Vice President, Operations McCrystle Adams Vice ",
|
| 384 |
+
"tool_call_id": null
|
| 385 |
+
},
|
| 386 |
+
{
|
| 387 |
+
"role": "assistant",
|
| 388 |
+
"content": "",
|
| 389 |
+
"reasoning_content": "Open around L230.",
|
| 390 |
+
"tool_calls": [
|
| 391 |
+
{
|
| 392 |
+
"id": null,
|
| 393 |
+
"type": "function",
|
| 394 |
+
"function": {
|
| 395 |
+
"name": "open",
|
| 396 |
+
"arguments": "{\"cursor\": 8, \"loc\": 220}"
|
| 397 |
+
}
|
| 398 |
+
}
|
| 399 |
+
]
|
| 400 |
+
},
|
| 401 |
+
{
|
| 402 |
+
"role": "tool",
|
| 403 |
+
"content": "[12] www.annualreports.com (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2022.pdf)\n**viewing lines [220 - 267] of 289**\n\nL220: contributions $28,946 Bequests, trusts and split interests $13,928 Income from \nL221: investments, annuity reserve funds and trusts (-$7,495) Royalties and other \nL222: income $744 Contributed services $5,047 Total Revenue $41,170 USES OF FUNDS \nL223: Biodiversity conservation $18,970 Constituency mobilization $16,528 Fundraising \nL224: $1,029 Management and general $6,354 Total Expenses $42,881 Change in net assets\nL225: (-$1,711) Net assets, start of year $45,144 Net Assets, End of the Year $43,433\nL226: Dollars are in thousands. 12 DEFENDERS OF WILDLIFE Grants and contributions 59%\nL227: Contributed services 10% Royalties and other income 2% Bequests, trusts and \nL228: split interests 29% TOTAL REVENUE Income from investments -15% Program and \nL229: support services 98% USE OF FUNDS Fundraising 2% ===== Page 13 ===== \nL230: DEFENDERS.ORG 13 ===== Page 14 ===== BOARD OF DIRECTORS John Dayton, Esq.* Chair\nL231: Texas Sheryl Sachs* Vice Chair Connecticut Dinah Bear, Esq.* Secretary Arizona \nL232: Mark Caylor* Treasurer District of Columbia Susan Alexander Connecticut Sylvia \nL233: Baca* California Whitefield Bailey Tennessee Donald Barry, Esq. Oregon Kim \nL234: O’Keefe Beck, Ph.D California Gabriela Chavarria, Ph.D Washington Jamie \nL235: Rappaport Clark* President & CEO Virginia John Donovan, Esq.* Montana and \nL236: California Caroline D. Gabel Maryland Terry L. Root, Ph.D New Mexico Thomas D. \nL237: Sisk, Ph.D British Columbia, Canada BOARD EMERITUS Terry C. Pelster, Esq. New \nL238: York *Executive Committee member* STAFF & ADVISORS SCIENCE ADVISORS Gabriela \nL239: Chavarria, Ph.D Burke Museum, University of Washington Leah Gerber, Ph.D Arizona\nL240: State University Kathayoon Khalil, Ph.D Oregon Zoo Rurik List, Ph.D Universidad\nL241: Autónoma Metropolitana-Lerma Barry Noon, Ph.D Colorado State University Terry \nL242: L. Root, Ph.D Stanford University Mark Schwartz, Ph.D University of California-\nL243: Davis Thomas D. Sisk, Ph.D Emeritus Professor Northern Arizona University David \nL244: S. Wilcox, Ph.D Princeton University Rae Wynn-Grant, Ph.D National Geographic \nL245: Society SENIOR STAFF Jamie Rappaport Clark President & CEO Thu Pham Chief of \nL246: Staff James Stofan Senior Vice President, Operations McCrystle Adams Vice \nL247: President, Conservation Law Matt Braughler Vice President, Philanthropy Rachel \nL248: Brittin Vice President, Communications Shawn Cantrell Vice President, Field \nL249: Conservation Programs Robert L. Dewey Vice President, Government Relations & \nL250: External Affairs Monica Goldberg Vice President, Landscape Conservation Sharon \nL251: Morris-Smith Vice President of Human Resources Elizabeth Nichols Vice President,\nL252: Finance/CFO Anthony Pegues Vice President, Diversity, Equity, Inclusion, \nL253: Justice Lindsay Rosa, Ph.D Vice President, Conservation Research and Innovation \nL254: Brandace Swimley Vice President, Integrated Marketing 14 DEFENDERS OF WILDLIFE \nL255: ===== Page 15 ===== There are many ways to support Defenders of Wildlife and \nL256: protect our imperiled wildlife. To learn more or donate, contact us at \nL257: 1-800-385-9712, visit Defenders.org/donate or choose one of the following \nL258: options. ➤ Transfer appreciated assets directly to Defenders and maximize \nL259: potential tax benefits. Defenders.org/ donate-stocks-help-save-wildlife ➤ Become\nL260: a Leadership Council member with a single donation of $1,000 or more and enjoy \nL261: more personal involvement with Defenders. Defenders.org/leadershipcouncil ➤ If \nL262: you are 70.5 or older, roll over a portion of your IRA to benefit wildlife. \nL263: Remember, these gifts must come directly from your IRA account. \nL264: Defenders.org/planned-giving/gifts-your-retirement-plan ➤ Get started on a \nL265: contribution from your donor-advised fund Defenders.org/donor-advised-funds ➤ \nL266: Check with your personnel office or that of your spouse/partner about your \nL267: company’s Corporate Matching Gifts program or visit us at ",
|
| 404 |
+
"tool_call_id": null
|
| 405 |
+
},
|
| 406 |
+
{
|
| 407 |
+
"role": "assistant",
|
| 408 |
+
"content": "",
|
| 409 |
+
"reasoning_content": "Thus the emeritus board member is Terry C. Pelster. However, the question might ask for \"Who was the emeritus board member that year?\" Possibly referring to the year of the annual report that mentioned the rescinded plan and contributed services decrease. That is 2022. So the answer is Terry C. Pelster.\n\nBut let's verify that the 2022 annual report indeed includes the mention of contributed services decreasing to 10%. We saw that. So answer is Terry C. Pelster.\n\nBut maybe the question is tricky: \"Who was the emeritus board member that year?\" Could be the emeritus board member listed in the 2021 annual report? However, the question says \"That same year, a company's annual report revealed that its nearly 2.2 million members and supporters contributed over $49 million, with 12% of total revenue coming from contributed services. The following year, the annual report stated that the organization had played a role in rescinding a previous administration’s plan to open most of the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas drilling and that contributed services had decreased by 2% to 10%.\"\n\nThus the \"following year\" annual report is 2022. The question likely asks: \"Who was the emeritus board member that year?\" Meaning the emeritus board member listed in that annual report (2022). So answer: Terry C. Pelster.\n\nBut let's confirm that the 2021 annual report also shows emeritus board member Terry C. Pelster. Indeed we saw that. But perhaps the 2022 report might have a different emeritus board member. We saw it's the same. So answer is Terry C. Pelster.\n\nHowever, the question might be about a different organization. Let's verify the details.\n\nFirst clue: Press release about Kenya vaccine doses on Dec 5, 2021. That is likely a World Bank press release. Search for \"World Bank Kenya vaccine doses December 2021 press release\".",
|
| 410 |
+
"tool_calls": [
|
| 411 |
+
{
|
| 412 |
+
"id": null,
|
| 413 |
+
"type": "function",
|
| 414 |
+
"function": {
|
| 415 |
+
"name": "search",
|
| 416 |
+
"arguments": "{\"query\": \"As of December 5, 2021, Kenya had received a total of 16,201,670 vaccines\", \"topn\": 10, \"source\": \"web\"}"
|
| 417 |
+
}
|
| 418 |
+
}
|
| 419 |
+
]
|
| 420 |
+
},
|
| 421 |
+
{
|
| 422 |
+
"role": "tool",
|
| 423 |
+
"content": "[13] As of December 5, 2021, Kenya had received a total of 16,201,670 vaccines (Search_Results/As of December 5, 2021, Kenya had received a total of 16,201,670 vaccines)\n**viewing lines [0 - 41] of 41**\n\nL0: \nL1: URL: Search_Results/As of December 5, 2021, Kenya had received a total of \nL2: 16,201,670 vaccines\nL3: # Search Results\nL4: \nL5: * 【0†Kenya's Economy is Showing Resilience as Output Rises ...; publish_date: \nL6: none†www.worldbank.org】 Dec 14, 2021 — As of December 5, 2021, Kenya had \nL7: received a total of 16,201,670 vaccines, with 7,583,134 administered. While \nL8: vaccine acceptance is ...\nL9: * 【1†Unmet need for COVID-19 vaccination coverage in Kenya - PMC; \nL10: publish_date: none†pmc.ncbi.nlm.nih.gov】 by SK Muchiri · 2022 · Cited by 42 — As\nL11: of December 2021, six counties had a vaccination coverage of less than 5%. \nL12: These counties include Garissa, Mandera, Marsabit, Tana River, Turkana, and ...\nL13: * 【2†MINISTRY OF HEALTH; publish_date: none†covidhub.mediacouncil.or.ke】 Dec \nL14: 1, 2021 — • Total Covid-19 Vaccines Received to date- 16,201,670 ... Table 10: \nL15: Vaccine Logistics Received in the Country as at 5th, December 2021.\nL16: * 【3†COVID-19 vaccination refusal trends in Kenya over 2021 - PMC; \nL17: publish_date: none†pmc.ncbi.nlm.nih.gov】 by RT Rego · 2023 · Cited by 21 — We \nL18: assessed vaccine refusal over time in Kenya, and characterized factors \nL19: associated with changes in vaccination refusal.\nL20: * 【4†Ciheb-Kenya on the Front Lines of the COVID-19 Vaccine ...; publish_date:\nL21: none†www.ciheb.org】 Of the 721,509 persons vaccinated, 409,711 are aged 58 \nL22: years and above, 143,050 are healthcare workers, 109,593 are teachers, and \nL23: 59,155 are security officers.\nL24: * 【5†proportion of fully vaccinated adults 23.3pc.; publish_date: \nL25: none†www.facebook.com】 COVID-19: KENYA administers 150632 new vaccinations; \nL26: total jabs given now 13782963; proportion of fully vaccinated adults 23.3pc.\nL27: * 【6†National COVID-19 Vaccines Deployment and ...; publish_date: \nL28: none†www.parliament.go.ke】 Kenya has a well-established immunization program and\nL29: a robust disease surveillance and response unit (DSRU) which serves as an early\nL30: warning system, to.\nL31: * 【7†Kenya: Vaccine Requirements Violate Rights; publish_date: \nL32: none†www.hrw.org】 Dec 13, 2021 — Kenya, with an estimated adult population of \nL33: 27.2 million and a total population of 55 million, has received approximately 23\nL34: million doses as ...\nL35: * 【8†Government gives 20 million a month to get vaccinated; publish_date: \nL36: none†www.bbc.com】 Nov 22, 2021 — Although less than 10% of Kenyans are \nL37: vaccinated, the government wants to avoid a surge over Christmas.\nL38: * 【9†ministry of health kenya covid-19 immunization status ...; publish_date: \nL39: none†www.health.go.ke】 May 15, 2022 — By the end of 2021 Kenya had administered \nL40: 10.1 million doses of 5 types of Covid-19 vaccines. During this period 4.2 \nL41: million people were ...",
|
| 424 |
+
"tool_call_id": null
|
| 425 |
+
},
|
| 426 |
+
{
|
| 427 |
+
"role": "assistant",
|
| 428 |
+
"content": "",
|
| 429 |
+
"reasoning_content": "Open result 0.",
|
| 430 |
+
"tool_calls": [
|
| 431 |
+
{
|
| 432 |
+
"id": null,
|
| 433 |
+
"type": "function",
|
| 434 |
+
"function": {
|
| 435 |
+
"name": "open",
|
| 436 |
+
"arguments": "{\"cursor\": 13, \"id\": 0}"
|
| 437 |
+
}
|
| 438 |
+
}
|
| 439 |
+
]
|
| 440 |
+
},
|
| 441 |
+
{
|
| 442 |
+
"role": "tool",
|
| 443 |
+
"content": "[14] www.worldbank.org (https://www.worldbank.org/en/news/press-release/2021/12/14/kenya-s-economy-is-showing-resilience-as-output-rises-above-pre-pandemic-levels-driven-by-a-rebound-in-the-services-sect)\n**viewing lines [0 - 52] of 61**\n\nL0: \nL1: URL: https://www.worldbank.org/en/news/press-release/2021/12/14/kenya-s-economy-\nL2: is-showing-resilience-as-output-rises-above-pre-pandemic-levels-driven-by-a-\nL3: rebound-in-the-services-sect\nL4: NAIROBI, December 14, 2021 — Kenya’s economy has demonstrated resilience to the \nL5: COVID-19 shock, with output in the first half of the year rising above pre-\nL6: pandemic levels. In 2021 as a whole, gross domestic product (GDP) is expected to\nL7: grow by 5%, one of the faster recoveries among Sub-Saharan African countries. \nL8: Overall economic performance is expected to be robust at 4.9% per year in \nL9: 2022-23, similar to the pre-pandemic pace (5% average annual growth from 2010 to\nL10: 2019). According to the 24th edition of the Kenya Economic Update, “From \nL11: Recovery to Better Jobs,” growth has been supported by rebounds in industry and,\nL12: especially, services. Agricultural output, however, fell by 0.5% year on year \nL13: in the first half of 2021 following a particularly strong performance in 2020, \nL14: partly due to below-average rains. Demand-side recovery has been supported by a \nL15: revival in private consumption, against a backdrop of improving employment \nL16: conditions and household incomes. “Kenya’s economy has shown considerable \nL17: resilience to the enormous shock of the pandemic, and this year is expected to \nL18: post one of the stronger growth rebounds in the region thanks to diversified \nL19: sources of growth and sound economic policies and management,” said Keith \nL20: Hansen, World Bank Country Director for Kenya. “However, poverty has increased, \nL21: and the buffers and coping mechanisms of households, firms, and the public \nL22: finances have been depleted.” Economic activity in Kenya has continued to adapt \nL23: to the pandemic and associated restrictions. A mix of containment measures, such\nL24: as a nightly curfew, were in effect through most of 2021, while more \nL25: economically disruptive measures such as lockdowns and travel restrictions were \nL26: phased, limiting the impact on economic activities. The vaccine rollout, which \nL27: had a slow start due to supply constraints, has picked up as new shipments of \nL28: vaccines have arrived, particularly since September. This has supported economic\nL29: recovery and growth through the third quarter of 2021. As of December 5, 2021, \nL30: Kenya had received a total of 16,201,670 vaccines, with 7,583,134 administered. \nL31: While vaccine acceptance is reportedly high there is still a long way to go \nL32: towards the government’s target of fully inoculating the adult population of \nL33: about 30 million by the end of 2022.As of December 6, 2021, about 10% of adults \nL34: (2.9 million people) had been fully vaccinated while another 16% (4.9 million \nL35: people) had received their first dose. The report also projects robust growth in\nL36: the medium-term. This outlook takes into account that some sub-sectors, such as\nL37: education, have bounced back strongly, but others such as international \nL38: tourism, have only partially and face a much more protracted recovery. The \nL39: anticipated further recovery of hotels and restaurants, trade, transport, and \nL40: other services, depends on substantial vaccination progress to help prevent new \nL41: waves of infections and associated containment measures. “Recent economic \nL42: performance has been strong and the outlook is positive, but in Kenya, as \nL43: everywhere, the future course of the pandemic remains a major source of \nL44: uncertainty, said Alex Sienaert, Senior Economist for Kenya. “To support further\nL45: recovery, reduce debt distress risks, and rebuild space for social and \nL46: development spending, it is critical that Kenya continues to implement medium-\nL47: term fiscal consolidation plans.” In addition to pandemic-related risks to the \nL48: outlook, a second key domestic risk factor stems from the drought conditions \nL49: which are affecting parts of the country and already causing severe hardship. \nL50: Should the drought intensify or spread, this would weigh on the near-term \nL51: economic outlook. Weaker global growth, higher-than-anticipated energy prices, \nL52: and tighter external financing conditions are the primary external risks. As ",
|
| 444 |
+
"tool_call_id": null
|
| 445 |
+
},
|
| 446 |
+
{
|
| 447 |
+
"role": "assistant",
|
| 448 |
+
"content": "",
|
| 449 |
+
"reasoning_content": "Thus first clue confirmed.\n\nSecond clue: Defenders of Wildlife 2021 annual report. Confirmed.\n\nThird clue: Defenders of Wildlife 2022 annual report. Confirmed.\n\nThus the answer is Terry C. Pelster.\n\nBut let's verify that the 2022 annual report indeed shows \"Contributed services 10%\". We saw that. Also confirm that 2021 report shows 12%. We saw that.\n\nThus the question: \"Who was the emeritus board member that year?\" Refers to 2022. Answer: Terry C. Pelster.\n\nHowever, the question might be asking for the emeritus board member in the 2021 report? Let's read the question carefully:\n\n\"In a year before 2023, between December 1 and 15 (inclusive), a press release reported that as of the 5th of that month, a country had received a total of 16,201,670 vaccine doses, with 7,583,134 administered. That same year, a company's annual report revealed that its nearly 2.2 million members and supporters contributed over $49 million, with 12% of total revenue coming from contributed services. The following year, the annual report stated that the organization had played a role in rescinding a previous administration’s plan to open most of the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas drilling and that contributed services had decreased by 2% to 10%. Who was the emeritus board member that year? Name only, no titles.\"\n\nThe phrase \"that year\" could refer to \"the following year\" i.e., the year of the annual report that mentioned the rescinded plan. Or could refer to \"that same year\" (the year of the press release and the first annual report). However, the phrase \"that year\" appears at the end: \"Who was the emeritus board member that year?\" It likely refers to the year of the annual report that is being discussed in the preceding sentence. The preceding sentence talks about the following year's annual report. So indeed \"that year\" is the following year (2022).\n\nThus answer: Terry C. Pelster.\n\nBut to be thorough, we should check the 2022 annual report for any other emeritus board members. The search only showed \"BOARD EMERITUS Terry C. Pelster, Esq.\" Maybe there are multiple emeritus board members. But likely only one.\n\nCheck the 2021 annual report for emeritus board member. It also shows Terry C. Pelster. So maybe the question is asking for the emeritus board member in the 2021 report. But why would they ask that? The question is about connecting the clues to identify the organization and then find the emeritus board member. The clues point to Defenders of Wildlife. The question likely asks for the emeritus board member as of the 2022 report.\n\nNevertheless, we should confirm that the 2022 report is indeed the one that mentions the rescinded plan. We saw that. Also confirm that contributed services decreased from 12% to 10%. We saw that.\n\nThus answer is Terry C. Pelster.\n\nBut let's search for \"Defenders of Wildlife emeritus board member 2022 Terry Pelster\".",
|
| 450 |
+
"tool_calls": [
|
| 451 |
+
{
|
| 452 |
+
"id": null,
|
| 453 |
+
"type": "function",
|
| 454 |
+
"function": {
|
| 455 |
+
"name": "search",
|
| 456 |
+
"arguments": "{\"query\": \"Terry C. Pelster Defenders of Wildlife emeritus board member\", \"topn\": 10, \"source\": \"web\"}"
|
| 457 |
+
}
|
| 458 |
+
}
|
| 459 |
+
]
|
| 460 |
+
},
|
| 461 |
+
{
|
| 462 |
+
"role": "tool",
|
| 463 |
+
"content": "[15] Terry C. Pelster Defenders of Wildlife emeritus board member (Search_Results/Terry C. Pelster Defenders of Wildlife emeritus board member)\n**viewing lines [0 - 31] of 31**\n\nL0: \nL1: URL: Search_Results/Terry C. Pelster Defenders of Wildlife emeritus board member\nL2: # Search Results\nL3: \nL4: * 【0†2024 impact report; publish_date: none†defenders.org】 Terry Root, Ph.D. \nL5: New Mexico. Thomas D. Sisk, Ph.D. British Columbia, Canada. BOARD EMERITUS. \nL6: Terry C. Pelster, Esq. New York. SCIENCE ADVISORS. Leah Gerber, Ph ...\nL7: * 【1†Defenders of Wildlife; publish_date: none†www.wrongkindofgreen.org】 \nL8: Directors ; Victor M. Sher*, Chair – California ; Terry C. Pelster*, Vice Chair \nL9: – New York ; Richard Kopcho*, Treasurer – California ; Adelaide P. Gomer*, \nL10: Secretary ...\nL11: * 【2†Exhibit 12; publish_date: none†www.uschamber.com】 DECLARATION OF TERRY \nL12: PELSTER. I, Terry C. Pelster, declare as follows: 1. I am a current member of \nL13: Defenders of Wildlife (“Defenders”) and have been a member.\nL14: * 【3†2020 ANNUAL REPORT; publish_date: none†defenders.org】 Terry L. Root. \nL15: Florida. BOARD. EMERITUS. Terry C. Pelster. New York. Alan Steinberg. Florida. \nL16: SCIENCE. ADVISORS. Gabriela Chavarria,. Ph.D. Denver Museum of.\nL17: * 【4†2019 Annual Report; publish_date: none†defenders.org】 BOARD EMERITUS. \nL18: Terry C. Pelster. New York. Alan Steinberg. Florida. SCIENCE ADVISORS. Leah \nL19: Gerber, Ph.D. Arizona State University. Kathayoon Khalil, Ph.D.\nL20: * 【5†annual report; publish_date: none†defenders.org】 * Executive Committee \nL21: member. BoARD EMERITuS. Terry C. Pelster. New York. Alan Steinberg. Florida. \nL22: PRESIDENT. EMERITuS. Rodger Schlickeisen. Virginia. SCIENCE ...\nL23: * 【6†BEING THERE FOR BELUGAS; publish_date: none†wendeenicole.com】 Mar 2, 2023\nL24: — Defenders of Wildlife is a national, nonprofit member- ship ... Terry C. \nL25: Pelster, Esq. New York. *Executive Committee member outfront.\nL26: * 【7†Annual Reports; publish_date: none†www.annualreports.com】 WAYS TO GIVE \nL27: There are many ways to support Defenders of Wildlife and protect our imperiled \nL28: wildlife. ... Terry C. Pelster. New York. Alan Steinberg. Florida.\nL29: * 【8†2014 Annual Report; publish_date: none†defenders.org】 BOARD OF DIRECTORS \nL30: defenders of wildlife is a national, nonprofit ... BOARD EMERITUS. Terry C. \nL31: Pelster. New York. Alan Steinberg. Florida. Page 3. PO.",
|
| 464 |
+
"tool_call_id": null
|
| 465 |
+
},
|
| 466 |
+
{
|
| 467 |
+
"role": "assistant",
|
| 468 |
+
"content": "",
|
| 469 |
+
"reasoning_content": "Thus Terry C. Pelster is indeed the emeritus board member.\n\nNow the question might want just \"Terry C. Pelster\". Or maybe \"Terry Pelster\". Or \"Terry C. Pelster, Esq.\" but instructions say \"Name only, no titles.\" So likely \"Terry C. Pelster\". However, maybe they want \"Terry Pelster\". Better to include full name as listed: \"Terry C. Pelster\".\n\nLet's read the question again: \"Who was the emeritus board member that year? Name only, no titles.\" So we should answer just the name, no \"Esq.\" or \"Board Emeritus\". So \"Terry C. Pelster\". Or maybe \"Terry Pelster\". But the document shows \"Terry C. Pelster, Esq.\" So the name is \"Terry C. Pelster\". \n\nBetter to verify that the 2022 annual report indeed lists \"BOARD EMERITUS Terry C. Pelster, Esq.\" We saw that line.\n\nThus answer: Terry C. Pelster.\n\nBut let's double-check that the question might refer to the 2021 annual report. The phrase \"that year\" could be ambiguous. Let's parse the timeline:\n\n- Year 1: 2021. Press release in Dec 2021 about Kenya vaccine doses. Same year (2021) annual report of Defenders of Wildlife shows 12% contributed services.\n\n- Year 2: 2022. Annual report mentions rescinded plan and contributed services decreased to 10%.\n\nThe question says \"The following year, the annual report stated that the organization had played a role in rescinding a previous administration’s plan ... and that contributed services had decreased by 2% to 10%.\" This is year 2.\n\nThen asks \"Who was the emeritus board member that year?\" That likely refers to year 2.\n\nThus answer: Terry C. Pelster.\n\nHowever, perhaps the emeritus board member changed between 2021 and 2022. We need to check 2022 annual report for any other emeritus board member. We saw only Terry C. Pelster. Also check 2021 annual report: same. So likely unchanged.\n\nThus answer is Terry C. Pelster.\n\nNevertheless, we should confirm that the 2022 annual report is indeed the one that includes the phrase \"BLM rescinded the previous administration’s plan that opened most of the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas drilling\". We saw that in line 200-202.\n\nThus answer is Terry C. Pelster.\n\nNow we need to provide the answer in the final message. Only the name.\n\nThus final answer: Terry C. Pelster.\n\nBut let's be thorough and search for \"Defenders of Wildlife 2022 annual report contributed services 10%\".",
|
| 470 |
+
"tool_calls": [
|
| 471 |
+
{
|
| 472 |
+
"id": null,
|
| 473 |
+
"type": "function",
|
| 474 |
+
"function": {
|
| 475 |
+
"name": "find",
|
| 476 |
+
"arguments": "{\"cursor\": 8, \"pattern\": \"Contributed services\"}"
|
| 477 |
+
}
|
| 478 |
+
}
|
| 479 |
+
]
|
| 480 |
+
},
|
| 481 |
+
{
|
| 482 |
+
"role": "tool",
|
| 483 |
+
"content": "[16] Find results for text: `contributed services` in `www.annualreports.com` (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2022.pdf/find?pattern=contributed services)\n**viewing lines [0 - 10] of 10**\n\nL0: # 【0†match at L222】\nL1: income $744 Contributed services $5,047 Total Revenue $41,170 USES OF FUNDS \nL2: Biodiversity conservation $18,970 Constituency mobilization $16,528 Fundraising \nL3: $1,029 Management and general $6,354 Total Expenses $42,881 Change in net assets\nL4: (-$1,711) Net assets, start of year $45,144 Net Assets, End of the Year $43,433\nL5: \nL6: # 【1†match at L227】\nL7: Contributed services 10% Royalties and other income 2% Bequests, trusts and \nL8: split interests 29% TOTAL REVENUE Income from investments -15% Program and \nL9: support services 98% USE OF FUNDS Fundraising 2% ===== Page 13 ===== \nL10: DEFENDERS.ORG 13 ===== Page 14 ===== BOARD OF DIRECTORS John Dayton, Esq.* Chair",
|
| 484 |
+
"tool_call_id": null
|
| 485 |
+
},
|
| 486 |
+
{
|
| 487 |
+
"role": "assistant",
|
| 488 |
+
"content": "",
|
| 489 |
+
"reasoning_content": "Thus confirmed.\n\nNow we should verify that the 2021 annual report shows contributed services 12%.",
|
| 490 |
+
"tool_calls": [
|
| 491 |
+
{
|
| 492 |
+
"id": null,
|
| 493 |
+
"type": "function",
|
| 494 |
+
"function": {
|
| 495 |
+
"name": "find",
|
| 496 |
+
"arguments": "{\"cursor\": 4, \"pattern\": \"Contributed services\"}"
|
| 497 |
+
}
|
| 498 |
+
}
|
| 499 |
+
]
|
| 500 |
+
},
|
| 501 |
+
{
|
| 502 |
+
"role": "tool",
|
| 503 |
+
"content": "[17] Find results for text: `contributed services` in `www.annualreports.com` (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2021.pdf/find?pattern=contributed services)\n**viewing lines [0 - 4] of 4**\n\nL0: # 【0†match at L194】\nL1: $3,354 Royalties and other income $3,576 Contributed services $6,140 Total \nL2: Revenue $49,819 USES OF FUNDS Biodiversity conservation $22,420 Constituency \nL3: mobilization $16,324 Fundraising $1,211 Management and general $5,865 Total \nL4: Expenses $45,820 Change in net assets $3,999 Net assets, start of year $41,145 ",
|
| 504 |
+
"tool_call_id": null
|
| 505 |
+
},
|
| 506 |
+
{
|
| 507 |
+
"role": "assistant",
|
| 508 |
+
"content": "",
|
| 509 |
+
"reasoning_content": "Open around L190-200 to see percentage.",
|
| 510 |
+
"tool_calls": [
|
| 511 |
+
{
|
| 512 |
+
"id": null,
|
| 513 |
+
"type": "function",
|
| 514 |
+
"function": {
|
| 515 |
+
"name": "open",
|
| 516 |
+
"arguments": "{\"cursor\": 4, \"loc\": 185}"
|
| 517 |
+
}
|
| 518 |
+
}
|
| 519 |
+
]
|
| 520 |
+
},
|
| 521 |
+
{
|
| 522 |
+
"role": "tool",
|
| 523 |
+
"content": "[18] www.annualreports.com (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2021.pdf)\n**viewing lines [185 - 232] of 261**\n\nL185: devastating water pollution that is killing the seagrass and causing manatees to\nL186: starve. DAVID TES | SAM FRENZY DRAW DEFENDERS.ORG 11 ===== Page 12 ===== In \nL187: 2021, Defenders of Wildlife’s nearly 2.2 million members and supporters \nL188: contributed more than $49 million for wildlife and wildlife habitat. This figure\nL189: includes all those who generously donated their time and expertise. The \nL190: steadfast support of our donors allows Defenders to sustain our program and \nL191: public education efforts in the field, the courts and on Capitol Hill. 2021 \nL192: SOURCES OF FUNDS Grants and contributions $29,057 Bequests, trusts and split \nL193: interests $7,692 Income from investments, annuity reserve funds and trusts \nL194: $3,354 Royalties and other income $3,576 Contributed services $6,140 Total \nL195: Revenue $49,819 USES OF FUNDS Biodiversity conservation $22,420 Constituency \nL196: mobilization $16,324 Fundraising $1,211 Management and general $5,865 Total \nL197: Expenses $45,820 Change in net assets $3,999 Net assets, start of year $41,145 \nL198: Net Assets, End of the Year $45,144 Dollars are in thousands. 12 DEFENDERS OF \nL199: WILDLIFE Grants and contributions 58% Income from investments 7% Requests, \nL200: trusts and split interests 15% Royalties and other income 7% Contributed \nL201: services 12% Program and support services 97% Fundraising 3% ===== Page 13 =====\nL202: DEFENDERS.ORG 13 ===== Page 14 ===== John Dayton, Esq.* Chair Texas Sheryl \nL203: Sachs* Vice Chair Connecticut Whitfield Bailey* Secretary Tennessee Mark Caylor*\nL204: Treasurer District of Columbia Sylvia Baca* California Donald Barry, Esq. \nL205: Oregon Dinah Bear, Esq. Arizona Kim O’Keefe Beck, Ph.D California Gabriela \nL206: Chavarria, Ph.D Washington Jamie Rappaport Clark* President & CEO Virginia \nL207: Caroline D. Gabel Maryland Keith M. Harper, Esq. Maryland John Donovan, Esq. \nL208: Montana and California James M. Hecker, Esq. Virginia Judith Ponsikoff, Ph.D* \nL209: California Terry L. Root, Ph.D Florida BOARD EMERITUS Terry C. Pelster, Esq. New\nL210: York *Executive Committee member* ST A F F & A D V I S O R S SCIENCE ADVISORS \nL211: Gabriela Chavarria, Ph.D Burke Museum, University of Washington Leah Gerber, \nL212: Ph.D Arizona State University Kathayoon Khalil, Ph.D Oregon Zoo Rurik List, Ph.D\nL213: Universidad Autónoma Metropolitana-Lerma Barry Noon, Ph.D Colorado State \nL214: University Terry L. Root, Ph.D Stanford University Mark Schwartz, Ph.D \nL215: University of California-Davis David S. Wilcox, Ph.D Princeton University Rae \nL216: Wynn-Grant, Ph.D National Geographic Society SENIOR STAFF Jamie Rappaport Clark \nL217: President & CEO Thu Pham Chief of Staff Renee Stone Senior Vice President, \nL218: Conservation Programs & General Counsel James Stefan Senior Vice President, \nL219: Operations Matt Braughler Vice President, Philanthropy Rachel Brittin Vice \nL220: President, Communications Shawn Cantrell Vice President, Field Conservation \nL221: Programs Robert L. Dewey Vice President, Government Relations & External Affairs\nL222: Monica Goldberg Vice President, Landscape Conservation Sharon Morris-Smith Vice\nL223: President of Human Resources Elizabeth Nichols Vice President, Finance/CFO \nL224: Anthony Pegues Vice President, Diversity, Equity, Inclusion, Justice Lindsay \nL225: Rosa, Ph.D Director, Center for Conservation Innovation Michael P. Senatore Vice\nL226: President, Conservation Law Brandace Swimley Vice President, Integrated \nL227: Marketing 14 DEFENDERS OF WILDLIFE ===== Page 15 ===== THERE ARE MANY WAYS TO \nL228: SUPPORT DEFENDERS OF WILDLIFE and protect our imperiled wildlife. To learn more \nL229: or donate, contact us at 1-800-385-9712, visit defenders.org/donate or choose \nL230: one of the following options. ➤ Transfer appreciated assets directly to \nL231: Defenders and maximize potential tax benefits. Defenders.org/donate-stocks-help-\nL232: save-wildlife ➤ Become a Leadership Council member with a single donation of ",
|
| 524 |
+
"tool_call_id": null
|
| 525 |
+
},
|
| 526 |
+
{
|
| 527 |
+
"role": "assistant",
|
| 528 |
+
"content": "Terry C. Pelster",
|
| 529 |
+
"reasoning_content": "Thus everything matches.\n\nThus answer: Terry C. Pelster.\n\nNow we need to output only the name.\n\nThus final answer: Terry C. Pelster.\n\nBut perhaps the question expects \"Terry Pelster\". However, the document includes middle initial \"C.\" It might be better to include the full name as listed: \"Terry C. Pelster\". The instruction \"Name only, no titles\" suggests we should not include \"Esq.\" or \"Board Emeritus\". But including middle initial is likely okay.\n\nTo be safe, we could output \"Terry C. Pelster\". Let's see similar puzzles: often they expect the full name as appears in the document.\n\nThus answer: Terry C. Pelster.\n\nNow we will provide final answer.",
|
| 530 |
+
"tool_calls": []
|
| 531 |
+
}
|
| 532 |
+
]
|
| 533 |
+
}
|
encoding/test_output.txt
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<|begin▁of▁sentence|>You are a helpful Assistant.
|
| 2 |
+
|
| 3 |
+
## Tools
|
| 4 |
+
|
| 5 |
+
You have access to a set of tools you can use to answer the user's question.
|
| 6 |
+
You can invoke functions by writing a "<|DSML|function_calls>" block like the following as part of your reply to the user:
|
| 7 |
+
<|DSML|function_calls>
|
| 8 |
+
<|DSML|invoke name="$FUNCTION_NAME">
|
| 9 |
+
<|DSML|parameter name="$PARAMETER_NAME" string="true|false">$PARAMETER_VALUE</|DSML|parameter>
|
| 10 |
+
...
|
| 11 |
+
</|DSML|invoke>
|
| 12 |
+
<|DSML|invoke name="$FUNCTION_NAME2">
|
| 13 |
+
...
|
| 14 |
+
</|DSML|invoke>
|
| 15 |
+
</|DSML|function_calls>
|
| 16 |
+
|
| 17 |
+
String and scalar parameters should be specified as is without any escaping or quotes, while lists and objects should use JSON format. The "string" attribute should be set to "true" for string type parameters and "false" for other types (numbers, booleans, arrays, objects).
|
| 18 |
+
|
| 19 |
+
If the thinking_mode is enabled, then after function results you should strongly consider outputting a thinking block. Here is an example:
|
| 20 |
+
|
| 21 |
+
<|DSML|function_calls>
|
| 22 |
+
...
|
| 23 |
+
</|DSML|function_calls>
|
| 24 |
+
|
| 25 |
+
<function_results>
|
| 26 |
+
...
|
| 27 |
+
</function_results>
|
| 28 |
+
|
| 29 |
+
<think>...thinking about results</think>
|
| 30 |
+
|
| 31 |
+
Here are the functions available in JSONSchema format:
|
| 32 |
+
<functions>
|
| 33 |
+
{"name": "get_datetime", "description": "Get the current date and time", "parameters": {"type": "object", "properties": {"timezone": {"type": "string", "description": "The timezone, e.g. Asia/Shanghai, UTC"}}, "required": ["timezone"]}}
|
| 34 |
+
{"name": "get_weather", "description": "Get the weather for a specific date and location", "parameters": {"type": "object", "properties": {"location": {"type": "string", "description": "The city name, e.g. Beijing, Hangzhou"}, "date": {"type": "string", "description": "The date in YYYY-MM-DD format"}}, "required": ["location", "date"]}}
|
| 35 |
+
</functions>
|
| 36 |
+
<|User|>明天杭州和北京的天气怎么样?<|Assistant|></think>
|
| 37 |
+
|
| 38 |
+
<|DSML|function_calls>
|
| 39 |
+
<|DSML|invoke name="get_datetime">
|
| 40 |
+
<|DSML|parameter name="timezone" string="true">Asia/Shanghai</|DSML|parameter>
|
| 41 |
+
</|DSML|invoke>
|
| 42 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 43 |
+
|
| 44 |
+
<function_results>
|
| 45 |
+
<result>{"current_date": "2024-01-15", "current_time": "14:30:00", "timezone": "Asia/Shanghai"}</result>
|
| 46 |
+
</function_results>
|
| 47 |
+
|
| 48 |
+
</think>
|
| 49 |
+
|
| 50 |
+
<|DSML|function_calls>
|
| 51 |
+
<|DSML|invoke name="get_weather">
|
| 52 |
+
<|DSML|parameter name="location" string="true">Hangzhou</|DSML|parameter>
|
| 53 |
+
<|DSML|parameter name="date" string="true">2024-01-16</|DSML|parameter>
|
| 54 |
+
</|DSML|invoke>
|
| 55 |
+
<|DSML|invoke name="get_weather">
|
| 56 |
+
<|DSML|parameter name="location" string="true">Beijing</|DSML|parameter>
|
| 57 |
+
<|DSML|parameter name="date" string="true">2024-01-16</|DSML|parameter>
|
| 58 |
+
</|DSML|invoke>
|
| 59 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 60 |
+
|
| 61 |
+
<function_results>
|
| 62 |
+
<result>{"location": "Hangzhou", "date": "2024-01-16", "temperature_high": "12", "temperature_low": "5", "weather": "多云", "humidity": "65%"}</result>
|
| 63 |
+
<result>{"location": "Beijing", "date": "2024-01-16", "temperature_high": "-2", "temperature_low": "-8", "weather": "晴", "humidity": "30%"}</result>
|
| 64 |
+
</function_results>
|
| 65 |
+
|
| 66 |
+
</think>根据查询结果,明天(2024年1月16日)的天气情况如下:
|
| 67 |
+
|
| 68 |
+
**杭州**:
|
| 69 |
+
- 天气:多云
|
| 70 |
+
- 最高温度:12°C
|
| 71 |
+
- 最低温度:5°C
|
| 72 |
+
- 湿度:65%
|
| 73 |
+
|
| 74 |
+
**北京**:
|
| 75 |
+
- 天气:晴
|
| 76 |
+
- 最高温度:-2°C
|
| 77 |
+
- 最低温度:-8°C
|
| 78 |
+
- 湿度:30%
|
| 79 |
+
|
| 80 |
+
杭州明天会比较温暖但有些多云,而北京会很冷但是晴天。建议在北京的朋友要注意保暖!<|end▁of▁sentence|><|User|>谢谢!那后天呢?<|Assistant|><think>用户现在问后天的天气,后天是2024-01-17,我可以直接查询(因为已知今天日期)🗓️</think>
|
| 81 |
+
|
| 82 |
+
<|DSML|function_calls>
|
| 83 |
+
<|DSML|invoke name="get_weather">
|
| 84 |
+
<|DSML|parameter name="location" string="true">Hangzhou</|DSML|parameter>
|
| 85 |
+
<|DSML|parameter name="date" string="true">2024-01-17</|DSML|parameter>
|
| 86 |
+
</|DSML|invoke>
|
| 87 |
+
<|DSML|invoke name="get_weather">
|
| 88 |
+
<|DSML|parameter name="location" string="true">Beijing</|DSML|parameter>
|
| 89 |
+
<|DSML|parameter name="date" string="true">2024-01-17</|DSML|parameter>
|
| 90 |
+
</|DSML|invoke>
|
| 91 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 92 |
+
|
| 93 |
+
<function_results>
|
| 94 |
+
<result>{"location": "Hangzhou", "date": "2024-01-17", "temperature_high": "15", "temperature_low": "8", "weather": "小雨", "humidity": "80%"}</result>
|
| 95 |
+
<result>{"location": "Beijing", "date": "2024-01-17", "temperature_high": "0", "temperature_low": "-6", "weather": "多云", "humidity": "45%"}</result>
|
| 96 |
+
</function_results>
|
| 97 |
+
|
| 98 |
+
<think>获取到后天的天气数据,整理回复给用户📝</think>后天(2024年1月17日)的天气情况:
|
| 99 |
+
|
| 100 |
+
**杭州**:
|
| 101 |
+
- 天气:小雨
|
| 102 |
+
- 最高温度:15°C
|
| 103 |
+
- 最低温度:8°C
|
| 104 |
+
- 湿度:80%
|
| 105 |
+
|
| 106 |
+
**北京**:
|
| 107 |
+
- 天气:多云
|
| 108 |
+
- 最高温度:0°C
|
| 109 |
+
- 最低温度:-6°C
|
| 110 |
+
- 湿度:45%
|
| 111 |
+
|
| 112 |
+
杭州后天会有小雨,温度略有回升,记得带伞。北京会稍微暖和一点,但依然��冷,请继续做好保暖措施。<|end▁of▁sentence|>
|
encoding/test_output_search_w_date.txt
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
encoding/test_output_search_wo_date.txt
ADDED
|
@@ -0,0 +1,1069 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
<|begin▁of▁sentence|><|User|>
|
| 2 |
+
|
| 3 |
+
## Tools
|
| 4 |
+
|
| 5 |
+
You have access to a set of tools you can use to answer the user's question.
|
| 6 |
+
You can invoke functions by writing a "<|DSML|function_calls>" block like the following as part of your reply to the user:
|
| 7 |
+
<|DSML|function_calls>
|
| 8 |
+
<|DSML|invoke name="$FUNCTION_NAME">
|
| 9 |
+
<|DSML|parameter name="$PARAMETER_NAME" string="true|false">$PARAMETER_VALUE</|DSML|parameter>
|
| 10 |
+
...
|
| 11 |
+
</|DSML|invoke>
|
| 12 |
+
<|DSML|invoke name="$FUNCTION_NAME2">
|
| 13 |
+
...
|
| 14 |
+
</|DSML|invoke>
|
| 15 |
+
</|DSML|function_calls>
|
| 16 |
+
|
| 17 |
+
String and scalar parameters should be specified as is without any escaping or quotes, while lists and objects should use JSON format. The "string" attribute should be set to "true" for string type parameters and "false" for other types (numbers, booleans, arrays, objects).
|
| 18 |
+
|
| 19 |
+
If the thinking_mode is enabled, then after function results you should strongly consider outputting a thinking block. Here is an example:
|
| 20 |
+
|
| 21 |
+
<|DSML|function_calls>
|
| 22 |
+
...
|
| 23 |
+
</|DSML|function_calls>
|
| 24 |
+
|
| 25 |
+
<function_results>
|
| 26 |
+
...
|
| 27 |
+
</function_results>
|
| 28 |
+
|
| 29 |
+
<think>...thinking about results</think>
|
| 30 |
+
|
| 31 |
+
Here are the functions available in JSONSchema format:
|
| 32 |
+
<functions>
|
| 33 |
+
{"name": "search", "description": "Searches for information related to query and displays topn results.", "parameters": {"type": "object", "properties": {"query": {"type": "string", "description": "The search query string"}, "topn": {"type": "integer", "description": "Number of top results to display", "default": 10}, "source": {"type": "string", "description": "Source to search within", "enum": ["web", "news"], "default": "web"}}, "required": ["query"], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#"}}
|
| 34 |
+
{"name": "open", "description": "Opens the link id from the page indicated by cursor starting at line number loc, showing num_lines lines. Valid link ids are displayed with the formatting: 【{id}†.*】. If cursor is not provided, the most recent page is implied. If id is a string, it is treated as a fully qualified URL associated with source. If loc is not provided, the viewport will be positioned at the beginning of the document or centered on the most relevant passage, if available. Use this function without id to scroll to a new location of an opened page.", "parameters": {"type": "object", "properties": {"id": {"description": "Link ID (number) or fully qualified URL (string)", "anyOf": [{"type": "integer"}, {"type": "string"}], "default": -1}, "cursor": {"type": "integer", "description": "Page cursor indicator", "default": -1}, "loc": {"type": "integer", "description": "Starting line number", "default": -1}, "num_lines": {"type": "integer", "description": "Number of lines to show", "default": -1}, "view_source": {"type": "boolean", "description": "Whether to view source", "default": false}, "source": {"type": "string", "description": "Source associated with the URL", "enum": ["web", "news"], "default": "web"}}, "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#"}}
|
| 35 |
+
{"name": "find", "description": "Finds exact matches of pattern in the current page, or the page given by cursor.", "parameters": {"type": "object", "properties": {"pattern": {"type": "string", "description": "The exact pattern to search for"}, "cursor": {"type": "integer", "description": "Page cursor to search in", "default": -1}}, "required": ["pattern"], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#"}}
|
| 36 |
+
{"name": "python", "description": "Use this tool to execute Python code. The code will not be shown to the user. This tool should be used for internal reasoning, but not for code that is intended to be visible to the user (e.g. when creating plots, tables, or files). When you send a message containing Python code to python, it will be executed in a stateful Jupyter notebook environment. python will respond with the output of the execution or time out after 120.0 seconds.", "parameters": {"type": "object", "properties": {"code": {"type": "string", "description": "The python code to execute in the jupyter environment."}}, "required": ["code"], "additionalProperties": false, "$schema": "http://json-schema.org/draft-07/schema#"}}
|
| 37 |
+
</functions>
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
# The user's message is: In a year before 2023, between December 1 and 15 (inclusive), a press release reported that as of the 5th of that month, a country had received a total of 16,201,670 vaccine doses, with 7,583,134 administered. That same year, a company's annual report revealed that its nearly 2.2 million members and supporters contributed over $49 million, with 12% of total revenue coming from contributed services. The following year, the annual report stated that the organization had played a role in rescinding a previous administration’s plan to open most of the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas drilling and that contributed services had decreased by 2% to 10%. Who was the emeritus board member that year? Name only, no titles.<|Assistant|><think>The user asks: "In a year before 2023, between December 1 and 15 (inclusive), a press release reported that as of the 5th of that month, a country had received a total of 16,201,670 vaccine doses, with 7,583,134 administered. That same year, a company's annual report revealed that its nearly 2.2 million members and supporters contributed over $49 million, with 12% of total revenue coming from contributed services. The following year, the annual report stated that the organization had played a role in rescinding a previous administration’s plan to open most of the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas drilling and that contributed services had decreased by 2% to 10%. Who was the emeritus board member that year? Name only, no titles."
|
| 41 |
+
|
| 42 |
+
We need to parse the puzzle.
|
| 43 |
+
|
| 44 |
+
We have clues about a press release about vaccine doses for a country, dated between Dec 1-15 inclusive, reporting as of 5th of that month total doses received 16,201,670 and administered 7,583,134. That is likely a COVID-19 vaccine update for some country. Which country? Might be a smaller country. Could be something like "Uganda", "Zimbabwe", "Kenya", "Philippines", etc. Let's search.
|
| 45 |
+
|
| 46 |
+
Search for "16,201,670 vaccine doses" "7,583,134 administered".</think>
|
| 47 |
+
|
| 48 |
+
<|DSML|function_calls>
|
| 49 |
+
<|DSML|invoke name="search">
|
| 50 |
+
<|DSML|parameter name="query" string="true">"16,201,670" vaccine doses</|DSML|parameter>
|
| 51 |
+
<|DSML|parameter name="topn" string="false">10</|DSML|parameter>
|
| 52 |
+
<|DSML|parameter name="source" string="true">web</|DSML|parameter>
|
| 53 |
+
</|DSML|invoke>
|
| 54 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 55 |
+
|
| 56 |
+
<function_results>
|
| 57 |
+
<result>[0] "16,201,670" vaccine doses (Search_Results/"16,201,670" vaccine doses)
|
| 58 |
+
**viewing lines [0 - 38] of 38**
|
| 59 |
+
|
| 60 |
+
L0:
|
| 61 |
+
L1: URL: Search_Results/"16,201,670" vaccine doses
|
| 62 |
+
L2: # Search Results
|
| 63 |
+
L3:
|
| 64 |
+
L4: * 【0†Kenya's Economy is Showing Resilience as Output Rises ...; publish_date:
|
| 65 |
+
L5: none†www.worldbank.org】 Dec 14, 2021 — As of December 5, 2021, Kenya had
|
| 66 |
+
L6: received a total of 16,201,670 vaccines, with 7,583,134 administered. While
|
| 67 |
+
L7: vaccine acceptance is ...
|
| 68 |
+
L8: * 【1†MINISTRY OF HEALTH; publish_date: none†covidhub.mediacouncil.or.ke】 Dec
|
| 69 |
+
L9: 1, 2021 — Total Doses Received 16,201,670. Table 10 gives the total vaccines
|
| 70 |
+
L10: received since the start of Covid -19 vaccination exercise in the country.
|
| 71 |
+
L11: * 【2†Output Result Page; publish_date: none†open.unicef.org】 ... 16,201,670
|
| 72 |
+
L12: doses of multiple vaccines nationwide and full vaccination of 15.5 per cent with
|
| 73 |
+
L13: two doses of COVID-19 vaccine as of 31 December 2021.
|
| 74 |
+
L14: * 【3†rebased GDP; publish_date: none†documents1.worldbank.org】 Dec 7, 2021 —
|
| 75 |
+
L15: As of December 5, 2021,. Kenya had received a total of 16,201,670 vaccines,
|
| 76 |
+
L16: with. 7,583,134 administered. Vaccine acceptance is reportedly high.
|
| 77 |
+
L17: * 【4†Integrated Annual Report; publish_date: none†www.co-opbank.co.ke】 May 27,
|
| 78 |
+
L18: 2022 — ... doses of Covid-19 vaccines and administered close to 17 million ...
|
| 79 |
+
L19: 16,201,670, huku 7,583,134 zikiwa tayari zimedungwa watu. Bado kuna ...
|
| 80 |
+
L20: * 【5†World Bank lifts Kenya's growth prospect to 5% in 2021; publish_date:
|
| 81 |
+
L21: none†www.africa-press.net】 ... 16,201,670 vaccines, with 7,583,134 administered.
|
| 82 |
+
L22: While vaccine acceptance is reportedly high there is still a long way to go
|
| 83 |
+
L23: towards the government's ...
|
| 84 |
+
L24: * 【6†2020 Annual Report United States; publish_date: none†www.hi-us.org】
|
| 85 |
+
L25: including medicine, vaccines, Covid-19 prevention kits, and kits of ...
|
| 86 |
+
L26: 16,201,670. 9,630,584. Prepaid expenses. 56,707. 22,601. Total current assets.
|
| 87 |
+
L27: * 【7†HOSPITAL CENTRAL DE LA DEFENSA; publish_date:
|
| 88 |
+
L28: none†contrataciondelestado.es】 16201670 X. URPA-URPA. 0. HCD-000393/00. KONTRON.
|
| 89 |
+
L29: 7000 ... LASER SHOT LBP-1120. CNEUR-C. NEUROFISIOLOGÍA. 0 ... VICTOREEN CT HEAD
|
| 90 |
+
L30: DOSE PHANTON. 43650-014.
|
| 91 |
+
L31: * 【8†body metal concentrations: Topics by ...; publish_date:
|
| 92 |
+
L32: none†www.science.gov】 PMID:16201670. Design Characteristics and Tobacco Metal
|
| 93 |
+
L33: Concentrations in Filtered Cigars. PubMed. Caruso, Rosalie V; O'Connor, Richard
|
| 94 |
+
L34: J; Travers, Mark J ...
|
| 95 |
+
L35: * 【9†Public Offices, Personal Demands: Capability in ...; publish_date:
|
| 96 |
+
L36: none†dokumen.pub】 ... (16201670).9 The Institutiones Politicae consists of two
|
| 97 |
+
L37: books. Book one deals with the origin, nature and goal of the commonwealth on
|
| 98 |
+
L38: the one hand, and the ...</result>
|
| 99 |
+
</function_results>
|
| 100 |
+
|
| 101 |
+
<think>Result shows Kenya. So the press release is about Kenya's vaccine doses as of Dec 5, 2021. The press release likely by World Bank or something. The search result shows "World Bank lifts Kenya's growth prospect..." maybe a press release dated Dec 14, 2021. But the clue says "between December 1 and 15 (inclusive), a press release reported that as of the 5th of that month, a country had received a total of 16,201,670 vaccine doses, with 7,583,134 administered." That matches Kenya on Dec 5, 2021. So the year is 2021.
|
| 102 |
+
|
| 103 |
+
Now the next clue: "That same year, a company's annual report revealed that its nearly 2.2 million members and supporters contributed over $49 million, with 12% of total revenue coming from contributed services."
|
| 104 |
+
|
| 105 |
+
This sounds like an environmental or conservation organization. "Nearly 2.2 million members and supporters contributed over $49 million." That might be something like "The Nature Conservancy", "World Wildlife Fund", "Sierra Club", "Environmental Defense Fund", "Natural Resources Defense Council", etc. Let's search.
|
| 106 |
+
|
| 107 |
+
Search for "nearly 2.2 million members and supporters contributed over $49 million" "12% of total revenue coming from contributed services".</think>
|
| 108 |
+
|
| 109 |
+
<|DSML|function_calls>
|
| 110 |
+
<|DSML|invoke name="search">
|
| 111 |
+
<|DSML|parameter name="query" string="true">"nearly 2.2 million members" "contributed over $49 million"</|DSML|parameter>
|
| 112 |
+
<|DSML|parameter name="topn" string="false">10</|DSML|parameter>
|
| 113 |
+
<|DSML|parameter name="source" string="true">web</|DSML|parameter>
|
| 114 |
+
</|DSML|invoke>
|
| 115 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 116 |
+
|
| 117 |
+
<function_results>
|
| 118 |
+
<result>[1] "nearly 2.2 million members" "contributed over $49 million" (Search_Results/"nearly 2.2 million members" "contributed over $49 million")
|
| 119 |
+
**viewing lines [0 - 41] of 41**
|
| 120 |
+
|
| 121 |
+
L0:
|
| 122 |
+
L1: URL: Search_Results/"nearly 2.2 million members" "contributed over $49 million"
|
| 123 |
+
L2: # Search Results
|
| 124 |
+
L3:
|
| 125 |
+
L4: * 【0†The Global Good Fund, Microsoft and Goodwill join forces ...;
|
| 126 |
+
L5: publish_date: none†globalgoodfund.org】 Sep 28, 2022 — ... more than 2.2 million
|
| 127 |
+
L6: people. They additionally contribute close to $49 billion in local, state and
|
| 128 |
+
L7: federal tax revenues. When COVID hit ...
|
| 129 |
+
L8: * 【1†Almost 22 billion American tax dollars spent to wipe out a ...;
|
| 130 |
+
L9: publish_date: none†www.facebook.com】 US military funding for Israel's war crimes
|
| 131 |
+
L10: in Lebanon and Gaza has now cost US taxpayers over $22 billion. When millions
|
| 132 |
+
L11: struggle to afford the ...
|
| 133 |
+
L12: * 【2†Corporate America has largely abandoned its post-January ...;
|
| 134 |
+
L13: publish_date: none†www.citizensforethics.org】 Jul 29, 2025 — Since the January 6
|
| 135 |
+
L14: insurrection, over 2,000 corporate and industry group PACs have given over $174
|
| 136 |
+
L15: million to members of the Sedition ...
|
| 137 |
+
L16: * 【3†Audit shows millions in questionable taxpayer spending at ...;
|
| 138 |
+
L17: publish_date: none†www.aol.com】 18 hours ago — ... nearly doubled from 1.3
|
| 139 |
+
L18: million to about 2.2 million. That is more than one in four Washington state
|
| 140 |
+
L19: residents receiving Medicaid, and the ...
|
| 141 |
+
L20: * 【4†Incarceration and Poverty in the United States - AAF; publish_date:
|
| 142 |
+
L21: none†www.americanactionforum.org】 Jun 30, 2020 — The United States currently
|
| 143 |
+
L22: incarcerates 2.2 million people, nearly half of whom are non-violent drug
|
| 144 |
+
L23: offenders, accused people held pre ...
|
| 145 |
+
L24: * 【5†How the NRA Spends Revenue (2023); publish_date: none†paddockpost.com】
|
| 146 |
+
L25: Apr 25, 2025 — In 2023, the NRA reported total revenue of $176 million (compared
|
| 147 |
+
L26: to $211 million in 2022, $227 million in 2021, $282 million in 2020, $292 ...
|
| 148 |
+
L27: * 【6†NCA Newsroom; publish_date: none†www.ncausa.org】 ... 2.2 million U.S.
|
| 149 |
+
L28: jobs—operating in every U.S. state and territory and contributing nearly $350
|
| 150 |
+
L29: billion to the U.S. economy every year. For media inquiries ...
|
| 151 |
+
L30: * 【7†The Early Childhood Educator Workforce; publish_date:
|
| 152 |
+
L31: none†cscce.berkeley.edu】 About 2.2 million adults are paid to care for and
|
| 153 |
+
L32: educate more than 9.7 million children between birth and age five in center-
|
| 154 |
+
L33: based and home-based settings.
|
| 155 |
+
L34: * 【8†Bringing Out the Worst in Congress: CRA By the Numbers ...; publish_date:
|
| 156 |
+
L35: none†progressivereform.org】 Jul 14, 2025 — In fact, the top ten recipients (out
|
| 157 |
+
L36: of 25) account for almost $7 million, showing how these contributions are
|
| 158 |
+
L37: targeted and strategic. Real ...
|
| 159 |
+
L38: * 【9†Club 100: Over 100 Americans gave more than $100000 to ...; publish_date:
|
| 160 |
+
L39: none†publicintegrity.org】 Jan 7, 2022 — Through Internet investments during the
|
| 161 |
+
L40: 1990s, he attracted 2.2 million online accounts valued at $174 million. Schwab
|
| 162 |
+
L41: has been a vocal ...</result>
|
| 163 |
+
</function_results>
|
| 164 |
+
|
| 165 |
+
<think>Not that. Try search for "2.2 million members and supporters contributed over $49 million".</think>
|
| 166 |
+
|
| 167 |
+
<|DSML|function_calls>
|
| 168 |
+
<|DSML|invoke name="search">
|
| 169 |
+
<|DSML|parameter name="query" string="true">"2.2 million members" "contributed over $49"</|DSML|parameter>
|
| 170 |
+
<|DSML|parameter name="topn" string="false">10</|DSML|parameter>
|
| 171 |
+
<|DSML|parameter name="source" string="true">web</|DSML|parameter>
|
| 172 |
+
</|DSML|invoke>
|
| 173 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 174 |
+
|
| 175 |
+
<function_results>
|
| 176 |
+
<result>[2] "2.2 million members" "contributed over $49" (Search_Results/"2.2 million members" "contributed over $49")
|
| 177 |
+
**viewing lines [0 - 2] of 2**
|
| 178 |
+
|
| 179 |
+
L0:
|
| 180 |
+
L1: URL: Search_Results/"2.2 million members" "contributed over $49"
|
| 181 |
+
L2: # Search Results</result>
|
| 182 |
+
</function_results>
|
| 183 |
+
|
| 184 |
+
<think>Maybe it's an annual report of a non-profit. Search for "annual report 2.2 million members contributed $49 million".</think>
|
| 185 |
+
|
| 186 |
+
<|DSML|function_calls>
|
| 187 |
+
<|DSML|invoke name="search">
|
| 188 |
+
<|DSML|parameter name="query" string="true">"2.2 million members" "annual report" $49 million</|DSML|parameter>
|
| 189 |
+
<|DSML|parameter name="topn" string="false">10</|DSML|parameter>
|
| 190 |
+
<|DSML|parameter name="source" string="true">web</|DSML|parameter>
|
| 191 |
+
</|DSML|invoke>
|
| 192 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 193 |
+
|
| 194 |
+
<function_results>
|
| 195 |
+
<result>[3] "2.2 million members" "annual report" $49 million (Search_Results/"2.2 million members" "annual report" $49 million)
|
| 196 |
+
**viewing lines [0 - 36] of 36**
|
| 197 |
+
|
| 198 |
+
L0:
|
| 199 |
+
L1: URL: Search_Results/"2.2 million members" "annual report" $49 million
|
| 200 |
+
L2: # Search Results
|
| 201 |
+
L3:
|
| 202 |
+
L4: * 【0†20-F; publish_date: none†www.sec.gov】 ANNUAL REPORT PURSUANT TO SECTION
|
| 203 |
+
L5: ... Our membership grew from 2.1 million members as at December 31, 2023 to 2.2
|
| 204 |
+
L6: million members as at December 31, 2024.
|
| 205 |
+
L7: * 【1†Oportun Reports Fourth Quarter and Full Year 2023 ...; publish_date:
|
| 206 |
+
L8: none†investor.oportun.com】 Mar 12, 2024 — Oportun (Nasdaq: OPRT) is a mission-
|
| 207 |
+
L9: driven fintech that puts its 2.2 million members' financial goals within reach.
|
| 208 |
+
L10: ... annual report on ...
|
| 209 |
+
L11: * 【2†2 0 21; publish_date: none†www.annualreports.com】 ANNUAL REPORT. 2. 0.
|
| 210 |
+
L12: 21. 2. 0. 21. Page 2. 2. DEFENDERS OF WILDLIFE. 2. 0. 21. 2. 0. 21 ... In 2021,
|
| 211 |
+
L13: Defenders of Wildlife's nearly 2.2 million members and.
|
| 212 |
+
L14: * 【3†Annual report and accounts 2020; publish_date: none†www.3i.com】
|
| 213 |
+
L15: Disclaimer. The Annual report and accounts have been prepared solely to provide
|
| 214 |
+
L16: information to shareholders. ... 2.2 million members. In December 2019, we sold
|
| 215 |
+
L17: ...
|
| 216 |
+
L18: * 【4†united states securities and exchange commission; publish_date:
|
| 217 |
+
L19: none†s21.q4cdn.com】 Dec 14, 2018 — ☒ ANNUAL REPORT ... approximately 5.7 million
|
| 218 |
+
L20: Members, including approximately 2.2 million Members from the acquisition of
|
| 219 |
+
L21: Best Doctors.
|
| 220 |
+
L22: * 【5†securities and exchange commission; publish_date: none†www.sec.gov】 ...
|
| 221 |
+
L23: Annual Report on Form 10-K filed with the SEC on March 10, 2020. The ... 2.2
|
| 222 |
+
L24: million members at June 30, 2020. The following table highlights the ...
|
| 223 |
+
L25: * 【6†2022-23 Annual Comprehensive Financial Report - CalPERS; publish_date:
|
| 224 |
+
L26: none†www.calpers.ca.gov】 Nov 17, 2023 — ... annual report is consistent with
|
| 225 |
+
L27: these accounting principles ... 2.2 million members and health benefit services
|
| 226 |
+
L28: to over 1.5 million ...
|
| 227 |
+
L29: * 【7†Medical Centers Report; publish_date:
|
| 228 |
+
L30: none†regents.universityofcalifornia.edu】 Oct 8, 2019 — which will allow its 2.2
|
| 229 |
+
L31: million members to receive advanced and ... annual report of the University of
|
| 230 |
+
L32: California. For the Medical ...
|
| 231 |
+
L33: * 【8†Working TogeTher to make HealtH care better; publish_date:
|
| 232 |
+
L34: none†www.unitedhealthgroup.com】 Feb 8, 2012 — ANNUAL REPORT PURSUANT TO SECTION
|
| 233 |
+
L35: 13 OR 15(d) OF THE ... approximately 2.2 million members enrolled in its
|
| 234 |
+
L36: Medicare. Advantage ...</result>
|
| 235 |
+
</function_results>
|
| 236 |
+
|
| 237 |
+
<think>Result 2 shows "Defenders of Wildlife". That might be the organization. Let's open.</think>
|
| 238 |
+
|
| 239 |
+
<|DSML|function_calls>
|
| 240 |
+
<|DSML|invoke name="open">
|
| 241 |
+
<|DSML|parameter name="cursor" string="false">3</|DSML|parameter>
|
| 242 |
+
<|DSML|parameter name="id" string="false">2</|DSML|parameter>
|
| 243 |
+
</|DSML|invoke>
|
| 244 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 245 |
+
|
| 246 |
+
<function_results>
|
| 247 |
+
<result>[4] www.annualreports.com (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2021.pdf)
|
| 248 |
+
**viewing lines [0 - 53] of 261**
|
| 249 |
+
|
| 250 |
+
L0:
|
| 251 |
+
L1: URL: https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-
|
| 252 |
+
L2: wildlife_2021.pdf
|
| 253 |
+
L3: ===== Page 1 ===== 2021 ANNUAL REPORT ===== Page 2 ===== # DEFENDERS OF WILDLIFE
|
| 254 |
+
L4: made important progress for imperiled species and vital landscapes across the
|
| 255 |
+
L5: United States in 2021. \--- **LAWYERS** immediately **challenged** the premature
|
| 256 |
+
L6: and reckless decision to strip **gray wolves** of federal **Endangered Species
|
| 257 |
+
L7: Act (ESA)** protections. For many decades, Defenders has led the effort to
|
| 258 |
+
L8: protect and restore the gray wolf, and we will continue to fight the
|
| 259 |
+
L9: unscientific and hostile anti-wolf policies that impede conservation progress
|
| 260 |
+
L10: and will carry on our unrelenting battle to restore federal protections for this
|
| 261 |
+
L11: iconic keystone species. \--- **LOBBYISTS** worked around the clock to keep
|
| 262 |
+
L12: wildlife and climate priorities in the **Infrastructure Investment and Jobs
|
| 263 |
+
L13: Act**. We also continue fighting to keep important wildlife and habitat funding
|
| 264 |
+
L14: in relevant **appropriations bills**. \--- 2 DEFENDERS OF WILDLIFE ===== Page 3
|
| 265 |
+
L15: ===== POLICY EXPERTS pushed forward on the urgent need for a National
|
| 266 |
+
L16: Biodiversity Strategy (NBS), an all-of-government approach to address the
|
| 267 |
+
L17: unprecedented loss of wildlife and habitat we are experiencing. We have coupled
|
| 268 |
+
L18: this with our new campaign to expand the National Wildlife Refuge System to
|
| 269 |
+
L19: preserve our nation’s only lands set aside for wildlife. By defending, funding
|
| 270 |
+
L20: and expanding our national wildlife refuges, we will directly address
|
| 271 |
+
L21: biodiversity loss and climate change while promoting increased equitable access
|
| 272 |
+
L22: to nature. FIELD TEAMS were on the ground helping to recover imperiled species.
|
| 273 |
+
L23: From panthers and sea turtles in Florida to wolves, bison and black-footed
|
| 274 |
+
L24: ferrets in Montana, Defenders’ conservation experts were in the field saving
|
| 275 |
+
L25: wildlife all over the country. CONSERVATION INNOVATION EXPERTS provided
|
| 276 |
+
L26: comprehensive analyses to guide policy and inform conservation strategies to
|
| 277 |
+
L27: reach the goal of protecting 30% of our terrestrial and marine systems by 2030
|
| 278 |
+
L28: (“30x30”). Defenders’ Center for Conservation Innovation (CCI) produced a report
|
| 279 |
+
L29: which details actions we need to take to achieve 30x30 while protecting
|
| 280 |
+
L30: biodiversity and addressing the climate crisis. DEFENDERS.ORG ===== Page 4 =====
|
| 281 |
+
L31: WE HAVE ACCOMPLISHED MUCH THIS YEAR WORKING WITH AN ADMINISTRATION THAT VALUES
|
| 282 |
+
L32: SCIENCE AND CONSERVATION. Our many successes include the return of protections
|
| 283 |
+
L33: to the Tongass National Forest in Alaska and the suspension of oil and gas
|
| 284 |
+
L34: leasing permits for the Arctic National Wildlife Refuge. Defenders also played a
|
| 285 |
+
L35: lead role in successfully defending the Migratory Bird Protection Act from
|
| 286 |
+
L36: attack and securing critical protections for migratory birds. Throughout 2021
|
| 287 |
+
L37: Defenders made important progress for the wildlife and wild places we all love,
|
| 288 |
+
L38: yet our nation’s wildlife still face unprecedented challenges. More and more
|
| 289 |
+
L39: species, including manatees, Mexican gray wolves, polar bears and North Atlantic
|
| 290 |
+
L40: right whales, face the very real threat of extinction because of climate
|
| 291 |
+
L41: change, habitat loss, pollution and inadequate protections. In our work we
|
| 292 |
+
L42: continue to demonstrate success by following the science, building partnerships,
|
| 293 |
+
L43: leading with innovative solutions and focusing on collaborative and practical
|
| 294 |
+
L44: approaches in defense of nature. Together we can make a lasting difference for
|
| 295 |
+
L45: wildlife and habitats. Your support is essential to our work and we couldn’t do
|
| 296 |
+
L46: it without you. Thank you for being an important part of our efforts to protect
|
| 297 |
+
L47: imperiled wildlife across our nation. Jamie Rappaport Clark President and CEO
|
| 298 |
+
L48: John Dayton Board Chair OUR NEW TELEVISION SERIES, WILDLIFE NATION WITH JEFF
|
| 299 |
+
L49: CORWIN, premiered in October and airs every weekend on ABC stations nationwide.
|
| 300 |
+
L50: This groundbreaking series takes Jeff across the country to meet Defenders’
|
| 301 |
+
L51: experts along with our science, tribal and community partners to educate and
|
| 302 |
+
L52: inspire viewers to join with Defenders to protect wildlife. While highlighting
|
| 303 |
+
L53: some of our important conservation work and raising awareness of important </result>
|
| 304 |
+
</function_results>
|
| 305 |
+
|
| 306 |
+
<think>Search within PDF for "2.2 million members".</think>
|
| 307 |
+
|
| 308 |
+
<|DSML|function_calls>
|
| 309 |
+
<|DSML|invoke name="find">
|
| 310 |
+
<|DSML|parameter name="cursor" string="false">4</|DSML|parameter>
|
| 311 |
+
<|DSML|parameter name="pattern" string="true">2.2</|DSML|parameter>
|
| 312 |
+
</|DSML|invoke>
|
| 313 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 314 |
+
|
| 315 |
+
<function_results>
|
| 316 |
+
<result>[5] Find results for text: `2.2` in `www.annualreports.com` (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2021.pdf/find?pattern=2.2)
|
| 317 |
+
**viewing lines [0 - 4] of 4**
|
| 318 |
+
|
| 319 |
+
L0: # 【0†match at L187】
|
| 320 |
+
L1: 2021, Defenders of Wildlife’s nearly 2.2 million members and supporters
|
| 321 |
+
L2: contributed more than $49 million for wildlife and wildlife habitat. This figure
|
| 322 |
+
L3: includes all those who generously donated their time and expertise. The
|
| 323 |
+
L4: steadfast support of our donors allows Defenders to sustain our program and </result>
|
| 324 |
+
</function_results>
|
| 325 |
+
|
| 326 |
+
<think>Open around L180.</think>
|
| 327 |
+
|
| 328 |
+
<|DSML|function_calls>
|
| 329 |
+
<|DSML|invoke name="open">
|
| 330 |
+
<|DSML|parameter name="cursor" string="false">4</|DSML|parameter>
|
| 331 |
+
<|DSML|parameter name="loc" string="false">170</|DSML|parameter>
|
| 332 |
+
</|DSML|invoke>
|
| 333 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 334 |
+
|
| 335 |
+
<function_results>
|
| 336 |
+
<result>[6] www.annualreports.com (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2021.pdf)
|
| 337 |
+
**viewing lines [170 - 215] of 261**
|
| 338 |
+
|
| 339 |
+
L170: into the wild. **10 DEFENDERS OF WILDLIFE** ===== Page 11 ===== AFTER ANOTHER
|
| 340 |
+
L171: SUCCESSFUL DEFENDERS LAWSUIT ON BEHALF OF THE CRITICALLY ENDANGERED RED WOLF,
|
| 341 |
+
L172: FWS reversed its decision to limit the recovery area and committed to a robust
|
| 342 |
+
L173: release strategy. After years of inaction, FWS released eight wolves to the wild
|
| 343 |
+
L174: in North Carolina and plan to release nine more wolves in the spring of 2022.
|
| 344 |
+
L175: This is an incredible win for this critically endangered species whose
|
| 345 |
+
L176: population has dwindled down to single digits in the wild because of
|
| 346 |
+
L177: mismanagement, vehicle strikes and poaching. DEFENDERS CONTINUED TO LEAD EFFORTS
|
| 347 |
+
L178: TO PROTECT THE FLORIDA MANATEE, a beloved species that suffered the deadliest
|
| 348 |
+
L179: year on record in 2021, tragically surpassing 1,000 deaths because of water
|
| 349 |
+
L180: pollution and lack of warm water habitat. Defenders led advocacy and education
|
| 350 |
+
L181: aimed at restoring the natural flow of the dammed Ocklawaha River, which would
|
| 351 |
+
L182: provide critical warm-water habitat that manatees need to survive. Defenders’
|
| 352 |
+
L183: legal team continued to fight for manatees in the courts, holding government
|
| 353 |
+
L184: agencies accountable for protecting critical habitat and addressing the
|
| 354 |
+
L185: devastating water pollution that is killing the seagrass and causing manatees to
|
| 355 |
+
L186: starve. DAVID TES | SAM FRENZY DRAW DEFENDERS.ORG 11 ===== Page 12 ===== In
|
| 356 |
+
L187: 2021, Defenders of Wildlife’s nearly 2.2 million members and supporters
|
| 357 |
+
L188: contributed more than $49 million for wildlife and wildlife habitat. This figure
|
| 358 |
+
L189: includes all those who generously donated their time and expertise. The
|
| 359 |
+
L190: steadfast support of our donors allows Defenders to sustain our program and
|
| 360 |
+
L191: public education efforts in the field, the courts and on Capitol Hill. 2021
|
| 361 |
+
L192: SOURCES OF FUNDS Grants and contributions $29,057 Bequests, trusts and split
|
| 362 |
+
L193: interests $7,692 Income from investments, annuity reserve funds and trusts
|
| 363 |
+
L194: $3,354 Royalties and other income $3,576 Contributed services $6,140 Total
|
| 364 |
+
L195: Revenue $49,819 USES OF FUNDS Biodiversity conservation $22,420 Constituency
|
| 365 |
+
L196: mobilization $16,324 Fundraising $1,211 Management and general $5,865 Total
|
| 366 |
+
L197: Expenses $45,820 Change in net assets $3,999 Net assets, start of year $41,145
|
| 367 |
+
L198: Net Assets, End of the Year $45,144 Dollars are in thousands. 12 DEFENDERS OF
|
| 368 |
+
L199: WILDLIFE Grants and contributions 58% Income from investments 7% Requests,
|
| 369 |
+
L200: trusts and split interests 15% Royalties and other income 7% Contributed
|
| 370 |
+
L201: services 12% Program and support services 97% Fundraising 3% ===== Page 13 =====
|
| 371 |
+
L202: DEFENDERS.ORG 13 ===== Page 14 ===== John Dayton, Esq.* Chair Texas Sheryl
|
| 372 |
+
L203: Sachs* Vice Chair Connecticut Whitfield Bailey* Secretary Tennessee Mark Caylor*
|
| 373 |
+
L204: Treasurer District of Columbia Sylvia Baca* California Donald Barry, Esq.
|
| 374 |
+
L205: Oregon Dinah Bear, Esq. Arizona Kim O’Keefe Beck, Ph.D California Gabriela
|
| 375 |
+
L206: Chavarria, Ph.D Washington Jamie Rappaport Clark* President & CEO Virginia
|
| 376 |
+
L207: Caroline D. Gabel Maryland Keith M. Harper, Esq. Maryland John Donovan, Esq.
|
| 377 |
+
L208: Montana and California James M. Hecker, Esq. Virginia Judith Ponsikoff, Ph.D*
|
| 378 |
+
L209: California Terry L. Root, Ph.D Florida BOARD EMERITUS Terry C. Pelster, Esq. New
|
| 379 |
+
L210: York *Executive Committee member* ST A F F & A D V I S O R S SCIENCE ADVISORS
|
| 380 |
+
L211: Gabriela Chavarria, Ph.D Burke Museum, University of Washington Leah Gerber,
|
| 381 |
+
L212: Ph.D Arizona State University Kathayoon Khalil, Ph.D Oregon Zoo Rurik List, Ph.D
|
| 382 |
+
L213: Universidad Autónoma Metropolitana-Lerma Barry Noon, Ph.D Colorado State
|
| 383 |
+
L214: University Terry L. Root, Ph.D Stanford University Mark Schwartz, Ph.D
|
| 384 |
+
L215: University of California-Davis David S. Wilcox, Ph.D Princeton University Rae </result>
|
| 385 |
+
</function_results>
|
| 386 |
+
|
| 387 |
+
<think>Scrolling further for "Contributed services 12%". Already seen. So the annual report is Defenders of Wildlife 2021 annual report.
|
| 388 |
+
|
| 389 |
+
Next clue: "The following year, the annual report stated that the organization had played a role in rescinding a previous administration’s plan to open most of the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas drilling and that contributed services had decreased by 2% to 10%."
|
| 390 |
+
|
| 391 |
+
Thus, the following year (2022) annual report of Defenders of Wildlife includes mention of rescinding plan to open most of 22 million acres of NPR-A to oil and gas drilling. Also contributed services decreased to 10% (from 12% in 2021). So we need to find the 2022 annual report for Defenders of Wildlife.
|
| 392 |
+
|
| 393 |
+
Search for "Defenders of Wildlife 2022 annual report National Petroleum Reserve Alaska".</think>
|
| 394 |
+
|
| 395 |
+
<|DSML|function_calls>
|
| 396 |
+
<|DSML|invoke name="search">
|
| 397 |
+
<|DSML|parameter name="query" string="true">Defenders of Wildlife 2022 annual report National Petroleum Reserve Alaska</|DSML|parameter>
|
| 398 |
+
<|DSML|parameter name="topn" string="false">10</|DSML|parameter>
|
| 399 |
+
<|DSML|parameter name="source" string="true">web</|DSML|parameter>
|
| 400 |
+
</|DSML|invoke>
|
| 401 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 402 |
+
|
| 403 |
+
<function_results>
|
| 404 |
+
<result>[7] Defenders of Wildlife 2022 annual report National Petroleum Reserve Alaska (Search_Results/Defenders of Wildlife 2022 annual report National Petroleum Reserve Alaska)
|
| 405 |
+
**viewing lines [0 - 37] of 37**
|
| 406 |
+
|
| 407 |
+
L0:
|
| 408 |
+
L1: URL: Search_Results/Defenders of Wildlife 2022 annual report National Petroleum
|
| 409 |
+
L2: Reserve Alaska
|
| 410 |
+
L3: # Search Results
|
| 411 |
+
L4:
|
| 412 |
+
L5: * 【0†CELEBRATING YEARS; publish_date: none†www.annualreports.com】 With less
|
| 413 |
+
L6: than 340 right whales left in the wild, Defenders is fighting tirelessly to end
|
| 414 |
+
L7: deadly lobster gear entanglements and vessel strikes that are driving ...
|
| 415 |
+
L8: * 【1†Financials; publish_date: none†defenders.org】 We invite you to explore
|
| 416 |
+
L9: the reports below to learn more about our activities and accomplishments, and
|
| 417 |
+
L10: how we put your money to work for wildlife.
|
| 418 |
+
L11: * 【2†Alaska Program Looks Back on 2022; publish_date: none†defenders.org】 Feb
|
| 419 |
+
L12: 9, 2023 — Thanks to a lawsuit joined by Defenders, seven million acres were
|
| 420 |
+
L13: returned to protection within the National Petroleum Reserve-Alaska (NPR-A), ...
|
| 421 |
+
L14: * 【3†Defenders-of-Wildlife-2022-Financial-Statement. ...; publish_date:
|
| 422 |
+
L15: none†defenders.org】 We have audited the accompanying consolidated financial
|
| 423 |
+
L16: statements of Defenders of Wildlife and Affiliated Defenders of Wildlife Action
|
| 424 |
+
L17: Fund (collectively, ...
|
| 425 |
+
L18: * 【4†2022 Annual Report; publish_date: none†alaskaconservation.org】 Jun 13,
|
| 426 |
+
L19: 2023 — In 2022, we focused on three landscapes: the Arctic. National Wildlife
|
| 427 |
+
L20: Refuge, Bristol Bay, and the Tongass National Forest. In March 2022,.
|
| 428 |
+
L21: * 【5†Assessment of ecological and cultural values within the ...;
|
| 429 |
+
L22: publish_date: none†www.blm.gov】 This document was written to provide technical
|
| 430 |
+
L23: information regarding the ecological importance of the National Petroleum
|
| 431 |
+
L24: Reserve – Alaska (NPR-A). Several ...
|
| 432 |
+
L25: * 【6†Accomplishments Report; publish_date: none†defenders.org】 National
|
| 433 |
+
L26: Petroleum Reserve-Alaska. Identified for exceptional wildlife and cultural
|
| 434 |
+
L27: values, including critical habitat for polar bears and other species ...
|
| 435 |
+
L28: * 【7†2022 annual report; publish_date: none†dory-
|
| 436 |
+
L29: plantain-s2zc.squarespace.com】 These projects are made possible through
|
| 437 |
+
L30: collaborations with Defenders of. Wildlife, Cook Inletkeeper, Trustees for
|
| 438 |
+
L31: Alaska,. Environmental Investigation Agency, ...
|
| 439 |
+
L32: * 【8†23IMPACT REPORT; publish_date: none†www.annualreports.com】 Defenders of
|
| 440 |
+
L33: Wildlife made incredible progress protecting wildlife and wild places in 2023,
|
| 441 |
+
L34: helping shape a brighter future for imperiled species and vital ...
|
| 442 |
+
L35: * 【9†From Leasing to Land Protections; publish_date: none†defenders-cci.org】
|
| 443 |
+
L36: Abstract. When you hear the name, National Petroleum Reserve - Alaska (NPR-A, or
|
| 444 |
+
L37: Reserve), you might think of a barren land filled with oil wells and ...</result>
|
| 445 |
+
</function_results>
|
| 446 |
+
|
| 447 |
+
<think>Open result 0.</think>
|
| 448 |
+
|
| 449 |
+
<|DSML|function_calls>
|
| 450 |
+
<|DSML|invoke name="open">
|
| 451 |
+
<|DSML|parameter name="cursor" string="false">7</|DSML|parameter>
|
| 452 |
+
<|DSML|parameter name="id" string="false">0</|DSML|parameter>
|
| 453 |
+
</|DSML|invoke>
|
| 454 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 455 |
+
|
| 456 |
+
<function_results>
|
| 457 |
+
<result>[8] www.annualreports.com (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2022.pdf)
|
| 458 |
+
**viewing lines [0 - 53] of 289**
|
| 459 |
+
|
| 460 |
+
L0:
|
| 461 |
+
L1: URL: https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-
|
| 462 |
+
L2: wildlife_2022.pdf
|
| 463 |
+
L3: ===== Page 1 ===== 2022 Impact Report C E L E B R A T I N G Y E A R S ===== Page
|
| 464 |
+
L4: 2 ===== 2022 Defenders of Wildlife made important progress for imperiled
|
| 465 |
+
L5: species and vital landscapes across the United States in 2022. GRAY WOLF | JIM
|
| 466 |
+
L6: GUMMERAL MAY STOCK PRIOR Lawyers successfully challenged the previous
|
| 467 |
+
L7: administration’s decision to delist the gray wolf and restored critical federal
|
| 468 |
+
L8: protections under the Endangered Species Act. This latest triumph in court is
|
| 469 |
+
L9: part of our ongoing battle to protect and restore gray wolves throughout their
|
| 470 |
+
L10: historical range and shield them from persecution by extremist legislators in
|
| 471 |
+
L11: Idaho, Montana and Wyoming. TWO MORE FATALIZED GRAY SWALLETS TO SEA TO SHARE
|
| 472 |
+
L12: ALLIANCE Lobbyists worked around the clock to expand funding for wildlife
|
| 473 |
+
L13: conservation in the FY2022 federal spending bill, which included $31 million (a
|
| 474 |
+
L14: 44% increase) for the Bureau of Land Management’s Threatened and Endangered
|
| 475 |
+
L15: Species Program, $2.5 million (an 81% increase) for the U.S. Department of
|
| 476 |
+
L16: Agriculture Wildlife Services’ Nonlethal Initiative to prevent human-wildlife
|
| 477 |
+
L17: conflicts and $21 million (a 320% increase) for North Atlantic right whale
|
| 478 |
+
L18: conservation. 2 DEFENDERS OF WILDLIFE ===== Page 3 ===== **Policy Experts**
|
| 479 |
+
L19: played a crucial role in securing international trade protections for 100
|
| 480 |
+
L20: species of sharks and rays, all 158 species of glass frogs and 73 species of
|
| 481 |
+
L21: reptiles, including 21 species of desert horned lizards, at the Convention on
|
| 482 |
+
L22: International Trade in Endangered Species (CITES) in Panama. \--- **Field
|
| 483 |
+
L23: Teams** worked tirelessly to protect and restore imperiled species across the
|
| 484 |
+
L24: country. From Florida manatees and red wolves in the Southeast to belugas and
|
| 485 |
+
L25: grizzly bears in Alaska, Defenders’ conservation experts were on the ground
|
| 486 |
+
L26: saving species that need our help to survive and thrive. \--- **Conservation
|
| 487 |
+
L27: Innovation Experts** published more than 10 peer-reviewed studies on topics that
|
| 488 |
+
L28: include the Cook Inlet beluga whale, golden-cheeked warbler, global parrot
|
| 489 |
+
L29: biodiversity, the Endangered Species Act, the effects of mountaintop removal
|
| 490 |
+
L30: mining on endangered species, the ecological importance of panthers and the
|
| 491 |
+
L31: implementation of “30x30” – the globally recognized goal to which President
|
| 492 |
+
L32: Biden committed the U.S. to conserve 30% of our imperiled lands and waters by
|
| 493 |
+
L33: 2030. \--- **DEFENDERS.ORG** ===== Page 4 ===== THANK YOU Defenders celebrated
|
| 494 |
+
L34: our 75th anniversary in 2022—an exciting milestone that we attribute to our
|
| 495 |
+
L35: unwavering dedication to our wildlife conservation mission. From helping to pass
|
| 496 |
+
L36: the Endangered Species Act and other bedrock conservation laws to leading the
|
| 497 |
+
L37: advocacy on the reintroduction of wolves to Yellowstone National Park and other
|
| 498 |
+
L38: parts of the West, Defenders is proud to inspire, lead and ultimately celebrate
|
| 499 |
+
L39: some of the most consequential conservation wins for wildlife and wild places.
|
| 500 |
+
L40: It is wonderfully fitting that we also mark 2022 as a year when we successfully
|
| 501 |
+
L41: defended, yet again, the original focal species and symbol of our organization,
|
| 502 |
+
L42: the gray wolf. While the future for gray wolves and many other species remains
|
| 503 |
+
L43: uncertain, we will never stop fighting to protect the imperiled wildlife that
|
| 504 |
+
L44: need us and to restore vibrant and balanced ecosystems. Our mission is more
|
| 505 |
+
L45: important than ever due to the escalating biodiversity and climate crises.
|
| 506 |
+
L46: Defenders is determined to build on our accomplishments and seize new
|
| 507 |
+
L47: opportunities to address these challenges through our multifaceted approach to
|
| 508 |
+
L48: conservation. We focus on developing innovative and science-based solutions,
|
| 509 |
+
L49: coordinating on-the-ground species and habitat restoration, promoting human-
|
| 510 |
+
L50: wildlife coexistence, protecting and strengthening our bedrock environmental
|
| 511 |
+
L51: laws, investing in impactful collaborations and partnerships, building a more
|
| 512 |
+
L52: diverse and powerful conservation movement and challenging attacks on wildlife
|
| 513 |
+
L53: through advocacy, policy and litigation. Defenders’ continued success is made </result>
|
| 514 |
+
</function_results>
|
| 515 |
+
|
| 516 |
+
<think>Search within PDF for "National Petroleum Reserve".</think>
|
| 517 |
+
|
| 518 |
+
<|DSML|function_calls>
|
| 519 |
+
<|DSML|invoke name="find">
|
| 520 |
+
<|DSML|parameter name="cursor" string="false">8</|DSML|parameter>
|
| 521 |
+
<|DSML|parameter name="pattern" string="true">Petroleum</|DSML|parameter>
|
| 522 |
+
</|DSML|invoke>
|
| 523 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 524 |
+
|
| 525 |
+
<function_results>
|
| 526 |
+
<result>[9] Find results for text: `petroleum` in `www.annualreports.com` (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2022.pdf/find?pattern=petroleum)
|
| 527 |
+
**viewing lines [0 - 4] of 4**
|
| 528 |
+
|
| 529 |
+
L0: # 【0†match at L201】
|
| 530 |
+
L1: the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas
|
| 531 |
+
L2: drilling and removed protections for important wildlife habitat. Protections
|
| 532 |
+
L3: have now been restored for nearly half of the reserve’s pristine lands, which
|
| 533 |
+
L4: are vital habitat for shorebirds, denning polar bears and tens of thousands of </result>
|
| 534 |
+
</function_results>
|
| 535 |
+
|
| 536 |
+
<think>Open around L190.</think>
|
| 537 |
+
|
| 538 |
+
<|DSML|function_calls>
|
| 539 |
+
<|DSML|invoke name="open">
|
| 540 |
+
<|DSML|parameter name="cursor" string="false">8</|DSML|parameter>
|
| 541 |
+
<|DSML|parameter name="loc" string="false">180</|DSML|parameter>
|
| 542 |
+
</|DSML|invoke>
|
| 543 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 544 |
+
|
| 545 |
+
<function_results>
|
| 546 |
+
<result>[10] www.annualreports.com (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2022.pdf)
|
| 547 |
+
**viewing lines [180 - 227] of 289**
|
| 548 |
+
|
| 549 |
+
L180: the sixth successful transfer of bison to the Assiniboine and Sioux Tribes of
|
| 550 |
+
L181: Fort Peck since 2019. \--- **SWIFT FIX KITS | © ROSIMA PAELARINTSKIMMA MADDIAL
|
| 551 |
+
L182: 200 AND CONSERVATION BIOLOGY INSTITUTE** \--- **Celebrating our third year** of
|
| 552 |
+
L183: a collaborative program with the Aaniih and Nakoda Tribes and others to restore
|
| 553 |
+
L184: swift foxes to the Fort Belknap Indian Reservation in Montana, Defenders helped
|
| 554 |
+
L185: with the release of 28 more swift foxes. With over 100 foxes reintroduced
|
| 555 |
+
L186: through this program, monitoring efforts show that they are reproducing in the
|
| 556 |
+
L187: wild—a critical measure of success for a self-sustaining population. \---
|
| 557 |
+
L188: **Defenders continued to lead the way** for conserving and recovering the
|
| 558 |
+
L189: endangered black-footed ferret, supporting the black-footed ferret survey for
|
| 559 |
+
L190: the Fort Belknap Indian community. Thirty-six ferrets were vaccinated against
|
| 560 |
+
L191: sylvatic plague and two dozen kits were released in the wild. \--- **10
|
| 561 |
+
L192: DEFENDERS OF WILDLIFE** ===== Page 11 ===== Defenders helped to bring hope for
|
| 562 |
+
L193: recovery for the endangered military macaw, adding 11 fledglings to a growing
|
| 563 |
+
L194: wild population in Puerta Vallarta, Mexico, that is under pressure from habitat
|
| 564 |
+
L195: loss and poachers for the illegal pet trade. Accord- ing to our recent report,
|
| 565 |
+
L196: the 2008 parrot trade ban that Defenders fought to achieve is working.
|
| 566 |
+
L197: Preventing more than 30,000 parrots from being illegally trapped each year, the
|
| 567 |
+
L198: trade ban has resulted in a 47% decrease in the illegal trade of parrots and an
|
| 568 |
+
L199: 88% decrease in U.S. seizures of Mexican parrots. As a result of a Defenders
|
| 569 |
+
L200: lawsuit, BLM rescinded the previous administration’s plan that opened most of
|
| 570 |
+
L201: the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas
|
| 571 |
+
L202: drilling and removed protections for important wildlife habitat. Protections
|
| 572 |
+
L203: have now been restored for nearly half of the reserve’s pristine lands, which
|
| 573 |
+
L204: are vital habitat for shorebirds, denning polar bears and tens of thousands of
|
| 574 |
+
L205: caribou in the Teshekpuk caribou herd. Our new storymap illustrates why the
|
| 575 |
+
L206: reserve is so important to wildlife. Defenders marked the 20th anniversary of
|
| 576 |
+
L207: our Sea Otter Awareness Week. In celebration of this milestone, we sponsored
|
| 577 |
+
L208: state legislation, signed by Gov. Gavin Newsom, that formally recognizes the
|
| 578 |
+
L209: event’s anniversary and acknowledges the vital role that sea otters play in
|
| 579 |
+
L210: California’s nearshore ecosystems. This annual celebration provides a unique
|
| 580 |
+
L211: opportunity to raise awareness of the important role sea otters play in
|
| 581 |
+
L212: maintaining ecosystem health, our need to coexist with sea otters and the
|
| 582 |
+
L213: efforts of Defenders and others in advancing sea otter conservation.
|
| 583 |
+
L214: DEFENDERS.ORG ===== Page 12 ===== FINANCIAL REPORT In 2022, Defenders of
|
| 584 |
+
L215: Wildlife’s nearly 2.2 million members and supporters contributed more than $41
|
| 585 |
+
L216: million for wildlife and wildlife habitat. This figure includes all those who
|
| 586 |
+
L217: generously donated their time and expertise. The steadfast support of our donors
|
| 587 |
+
L218: allows Defenders to sustain our program and public education efforts in the
|
| 588 |
+
L219: field, the courts and on Capitol Hill. 2022 SOURCES OF FUNDS Grants and
|
| 589 |
+
L220: contributions $28,946 Bequests, trusts and split interests $13,928 Income from
|
| 590 |
+
L221: investments, annuity reserve funds and trusts (-$7,495) Royalties and other
|
| 591 |
+
L222: income $744 Contributed services $5,047 Total Revenue $41,170 USES OF FUNDS
|
| 592 |
+
L223: Biodiversity conservation $18,970 Constituency mobilization $16,528 Fundraising
|
| 593 |
+
L224: $1,029 Management and general $6,354 Total Expenses $42,881 Change in net assets
|
| 594 |
+
L225: (-$1,711) Net assets, start of year $45,144 Net Assets, End of the Year $43,433
|
| 595 |
+
L226: Dollars are in thousands. 12 DEFENDERS OF WILDLIFE Grants and contributions 59%
|
| 596 |
+
L227: Contributed services 10% Royalties and other income 2% Bequests, trusts and </result>
|
| 597 |
+
</function_results>
|
| 598 |
+
|
| 599 |
+
<think>Scrolling a bit more for "Contributed services 10%". Already seen. So indeed the 2022 annual report shows contributed services 10%, down from 12% in 2021.
|
| 600 |
+
|
| 601 |
+
Thus the organization is Defenders of Wildlife.
|
| 602 |
+
|
| 603 |
+
The question: "Who was the emeritus board member that year? Name only, no titles."
|
| 604 |
+
|
| 605 |
+
We need to identify the emeritus board member listed in the 2022 annual report. From the 2021 annual report, we saw "BOARD EMERITUS Terry C. Pelster, Esq." However, that is for 2021. The question asks "Who was the emeritus board member that year?" That year refers to the following year (2022). So we need to check the 2022 annual report for the emeritus board member.
|
| 606 |
+
|
| 607 |
+
Open the 2022 PDF near the board list. Search for "Emeritus".</think>
|
| 608 |
+
|
| 609 |
+
<|DSML|function_calls>
|
| 610 |
+
<|DSML|invoke name="find">
|
| 611 |
+
<|DSML|parameter name="cursor" string="false">8</|DSML|parameter>
|
| 612 |
+
<|DSML|parameter name="pattern" string="true">Emeritus</|DSML|parameter>
|
| 613 |
+
</|DSML|invoke>
|
| 614 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 615 |
+
|
| 616 |
+
<function_results>
|
| 617 |
+
<result>[11] Find results for text: `emeritus` in `www.annualreports.com` (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2022.pdf/find?pattern=emeritus)
|
| 618 |
+
**viewing lines [0 - 10] of 10**
|
| 619 |
+
|
| 620 |
+
L0: # 【0†match at L237】
|
| 621 |
+
L1: Sisk, Ph.D British Columbia, Canada BOARD EMERITUS Terry C. Pelster, Esq. New
|
| 622 |
+
L2: York *Executive Committee member* STAFF & ADVISORS SCIENCE ADVISORS Gabriela
|
| 623 |
+
L3: Chavarria, Ph.D Burke Museum, University of Washington Leah Gerber, Ph.D Arizona
|
| 624 |
+
L4: State University Kathayoon Khalil, Ph.D Oregon Zoo Rurik List, Ph.D Universidad
|
| 625 |
+
L5:
|
| 626 |
+
L6: # 【1†match at L243】
|
| 627 |
+
L7: Davis Thomas D. Sisk, Ph.D Emeritus Professor Northern Arizona University David
|
| 628 |
+
L8: S. Wilcox, Ph.D Princeton University Rae Wynn-Grant, Ph.D National Geographic
|
| 629 |
+
L9: Society SENIOR STAFF Jamie Rappaport Clark President & CEO Thu Pham Chief of
|
| 630 |
+
L10: Staff James Stofan Senior Vice President, Operations McCrystle Adams Vice </result>
|
| 631 |
+
</function_results>
|
| 632 |
+
|
| 633 |
+
<think>Open around L230.</think>
|
| 634 |
+
|
| 635 |
+
<|DSML|function_calls>
|
| 636 |
+
<|DSML|invoke name="open">
|
| 637 |
+
<|DSML|parameter name="cursor" string="false">8</|DSML|parameter>
|
| 638 |
+
<|DSML|parameter name="loc" string="false">220</|DSML|parameter>
|
| 639 |
+
</|DSML|invoke>
|
| 640 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 641 |
+
|
| 642 |
+
<function_results>
|
| 643 |
+
<result>[12] www.annualreports.com (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2022.pdf)
|
| 644 |
+
**viewing lines [220 - 267] of 289**
|
| 645 |
+
|
| 646 |
+
L220: contributions $28,946 Bequests, trusts and split interests $13,928 Income from
|
| 647 |
+
L221: investments, annuity reserve funds and trusts (-$7,495) Royalties and other
|
| 648 |
+
L222: income $744 Contributed services $5,047 Total Revenue $41,170 USES OF FUNDS
|
| 649 |
+
L223: Biodiversity conservation $18,970 Constituency mobilization $16,528 Fundraising
|
| 650 |
+
L224: $1,029 Management and general $6,354 Total Expenses $42,881 Change in net assets
|
| 651 |
+
L225: (-$1,711) Net assets, start of year $45,144 Net Assets, End of the Year $43,433
|
| 652 |
+
L226: Dollars are in thousands. 12 DEFENDERS OF WILDLIFE Grants and contributions 59%
|
| 653 |
+
L227: Contributed services 10% Royalties and other income 2% Bequests, trusts and
|
| 654 |
+
L228: split interests 29% TOTAL REVENUE Income from investments -15% Program and
|
| 655 |
+
L229: support services 98% USE OF FUNDS Fundraising 2% ===== Page 13 =====
|
| 656 |
+
L230: DEFENDERS.ORG 13 ===== Page 14 ===== BOARD OF DIRECTORS John Dayton, Esq.* Chair
|
| 657 |
+
L231: Texas Sheryl Sachs* Vice Chair Connecticut Dinah Bear, Esq.* Secretary Arizona
|
| 658 |
+
L232: Mark Caylor* Treasurer District of Columbia Susan Alexander Connecticut Sylvia
|
| 659 |
+
L233: Baca* California Whitefield Bailey Tennessee Donald Barry, Esq. Oregon Kim
|
| 660 |
+
L234: O’Keefe Beck, Ph.D California Gabriela Chavarria, Ph.D Washington Jamie
|
| 661 |
+
L235: Rappaport Clark* President & CEO Virginia John Donovan, Esq.* Montana and
|
| 662 |
+
L236: California Caroline D. Gabel Maryland Terry L. Root, Ph.D New Mexico Thomas D.
|
| 663 |
+
L237: Sisk, Ph.D British Columbia, Canada BOARD EMERITUS Terry C. Pelster, Esq. New
|
| 664 |
+
L238: York *Executive Committee member* STAFF & ADVISORS SCIENCE ADVISORS Gabriela
|
| 665 |
+
L239: Chavarria, Ph.D Burke Museum, University of Washington Leah Gerber, Ph.D Arizona
|
| 666 |
+
L240: State University Kathayoon Khalil, Ph.D Oregon Zoo Rurik List, Ph.D Universidad
|
| 667 |
+
L241: Autónoma Metropolitana-Lerma Barry Noon, Ph.D Colorado State University Terry
|
| 668 |
+
L242: L. Root, Ph.D Stanford University Mark Schwartz, Ph.D University of California-
|
| 669 |
+
L243: Davis Thomas D. Sisk, Ph.D Emeritus Professor Northern Arizona University David
|
| 670 |
+
L244: S. Wilcox, Ph.D Princeton University Rae Wynn-Grant, Ph.D National Geographic
|
| 671 |
+
L245: Society SENIOR STAFF Jamie Rappaport Clark President & CEO Thu Pham Chief of
|
| 672 |
+
L246: Staff James Stofan Senior Vice President, Operations McCrystle Adams Vice
|
| 673 |
+
L247: President, Conservation Law Matt Braughler Vice President, Philanthropy Rachel
|
| 674 |
+
L248: Brittin Vice President, Communications Shawn Cantrell Vice President, Field
|
| 675 |
+
L249: Conservation Programs Robert L. Dewey Vice President, Government Relations &
|
| 676 |
+
L250: External Affairs Monica Goldberg Vice President, Landscape Conservation Sharon
|
| 677 |
+
L251: Morris-Smith Vice President of Human Resources Elizabeth Nichols Vice President,
|
| 678 |
+
L252: Finance/CFO Anthony Pegues Vice President, Diversity, Equity, Inclusion,
|
| 679 |
+
L253: Justice Lindsay Rosa, Ph.D Vice President, Conservation Research and Innovation
|
| 680 |
+
L254: Brandace Swimley Vice President, Integrated Marketing 14 DEFENDERS OF WILDLIFE
|
| 681 |
+
L255: ===== Page 15 ===== There are many ways to support Defenders of Wildlife and
|
| 682 |
+
L256: protect our imperiled wildlife. To learn more or donate, contact us at
|
| 683 |
+
L257: 1-800-385-9712, visit Defenders.org/donate or choose one of the following
|
| 684 |
+
L258: options. ➤ Transfer appreciated assets directly to Defenders and maximize
|
| 685 |
+
L259: potential tax benefits. Defenders.org/ donate-stocks-help-save-wildlife ➤ Become
|
| 686 |
+
L260: a Leadership Council member with a single donation of $1,000 or more and enjoy
|
| 687 |
+
L261: more personal involvement with Defenders. Defenders.org/leadershipcouncil ➤ If
|
| 688 |
+
L262: you are 70.5 or older, roll over a portion of your IRA to benefit wildlife.
|
| 689 |
+
L263: Remember, these gifts must come directly from your IRA account.
|
| 690 |
+
L264: Defenders.org/planned-giving/gifts-your-retirement-plan ➤ Get started on a
|
| 691 |
+
L265: contribution from your donor-advised fund Defenders.org/donor-advised-funds ➤
|
| 692 |
+
L266: Check with your personnel office or that of your spouse/partner about your
|
| 693 |
+
L267: company’s Corporate Matching Gifts program or visit us at </result>
|
| 694 |
+
</function_results>
|
| 695 |
+
|
| 696 |
+
<think>Thus the emeritus board member is Terry C. Pelster. However, the question might ask for "Who was the emeritus board member that year?" Possibly referring to the year of the annual report that mentioned the rescinded plan and contributed services decrease. That is 2022. So the answer is Terry C. Pelster.
|
| 697 |
+
|
| 698 |
+
But let's verify that the 2022 annual report indeed includes the mention of contributed services decreasing to 10%. We saw that. So answer is Terry C. Pelster.
|
| 699 |
+
|
| 700 |
+
But maybe the question is tricky: "Who was the emeritus board member that year?" Could be the emeritus board member listed in the 2021 annual report? However, the question says "That same year, a company's annual report revealed that its nearly 2.2 million members and supporters contributed over $49 million, with 12% of total revenue coming from contributed services. The following year, the annual report stated that the organization had played a role in rescinding a previous administration’s plan to open most of the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas drilling and that contributed services had decreased by 2% to 10%."
|
| 701 |
+
|
| 702 |
+
Thus the "following year" annual report is 2022. The question likely asks: "Who was the emeritus board member that year?" Meaning the emeritus board member listed in that annual report (2022). So answer: Terry C. Pelster.
|
| 703 |
+
|
| 704 |
+
But let's confirm that the 2021 annual report also shows emeritus board member Terry C. Pelster. Indeed we saw that. But perhaps the 2022 report might have a different emeritus board member. We saw it's the same. So answer is Terry C. Pelster.
|
| 705 |
+
|
| 706 |
+
However, the question might be about a different organization. Let's verify the details.
|
| 707 |
+
|
| 708 |
+
First clue: Press release about Kenya vaccine doses on Dec 5, 2021. That is likely a World Bank press release. Search for "World Bank Kenya vaccine doses December 2021 press release".</think>
|
| 709 |
+
|
| 710 |
+
<|DSML|function_calls>
|
| 711 |
+
<|DSML|invoke name="search">
|
| 712 |
+
<|DSML|parameter name="query" string="true">As of December 5, 2021, Kenya had received a total of 16,201,670 vaccines</|DSML|parameter>
|
| 713 |
+
<|DSML|parameter name="topn" string="false">10</|DSML|parameter>
|
| 714 |
+
<|DSML|parameter name="source" string="true">web</|DSML|parameter>
|
| 715 |
+
</|DSML|invoke>
|
| 716 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 717 |
+
|
| 718 |
+
<function_results>
|
| 719 |
+
<result>[13] As of December 5, 2021, Kenya had received a total of 16,201,670 vaccines (Search_Results/As of December 5, 2021, Kenya had received a total of 16,201,670 vaccines)
|
| 720 |
+
**viewing lines [0 - 41] of 41**
|
| 721 |
+
|
| 722 |
+
L0:
|
| 723 |
+
L1: URL: Search_Results/As of December 5, 2021, Kenya had received a total of
|
| 724 |
+
L2: 16,201,670 vaccines
|
| 725 |
+
L3: # Search Results
|
| 726 |
+
L4:
|
| 727 |
+
L5: * 【0†Kenya's Economy is Showing Resilience as Output Rises ...; publish_date:
|
| 728 |
+
L6: none†www.worldbank.org】 Dec 14, 2021 — As of December 5, 2021, Kenya had
|
| 729 |
+
L7: received a total of 16,201,670 vaccines, with 7,583,134 administered. While
|
| 730 |
+
L8: vaccine acceptance is ...
|
| 731 |
+
L9: * 【1†Unmet need for COVID-19 vaccination coverage in Kenya - PMC;
|
| 732 |
+
L10: publish_date: none†pmc.ncbi.nlm.nih.gov】 by SK Muchiri · 2022 · Cited by 42 — As
|
| 733 |
+
L11: of December 2021, six counties had a vaccination coverage of less than 5%.
|
| 734 |
+
L12: These counties include Garissa, Mandera, Marsabit, Tana River, Turkana, and ...
|
| 735 |
+
L13: * 【2†MINISTRY OF HEALTH; publish_date: none†covidhub.mediacouncil.or.ke】 Dec
|
| 736 |
+
L14: 1, 2021 — • Total Covid-19 Vaccines Received to date- 16,201,670 ... Table 10:
|
| 737 |
+
L15: Vaccine Logistics Received in the Country as at 5th, December 2021.
|
| 738 |
+
L16: * 【3†COVID-19 vaccination refusal trends in Kenya over 2021 - PMC;
|
| 739 |
+
L17: publish_date: none†pmc.ncbi.nlm.nih.gov】 by RT Rego · 2023 · Cited by 21 — We
|
| 740 |
+
L18: assessed vaccine refusal over time in Kenya, and characterized factors
|
| 741 |
+
L19: associated with changes in vaccination refusal.
|
| 742 |
+
L20: * 【4†Ciheb-Kenya on the Front Lines of the COVID-19 Vaccine ...; publish_date:
|
| 743 |
+
L21: none†www.ciheb.org】 Of the 721,509 persons vaccinated, 409,711 are aged 58
|
| 744 |
+
L22: years and above, 143,050 are healthcare workers, 109,593 are teachers, and
|
| 745 |
+
L23: 59,155 are security officers.
|
| 746 |
+
L24: * 【5†proportion of fully vaccinated adults 23.3pc.; publish_date:
|
| 747 |
+
L25: none†www.facebook.com】 COVID-19: KENYA administers 150632 new vaccinations;
|
| 748 |
+
L26: total jabs given now 13782963; proportion of fully vaccinated adults 23.3pc.
|
| 749 |
+
L27: * 【6†National COVID-19 Vaccines Deployment and ...; publish_date:
|
| 750 |
+
L28: none†www.parliament.go.ke】 Kenya has a well-established immunization program and
|
| 751 |
+
L29: a robust disease surveillance and response unit (DSRU) which serves as an early
|
| 752 |
+
L30: warning system, to.
|
| 753 |
+
L31: * 【7†Kenya: Vaccine Requirements Violate Rights; publish_date:
|
| 754 |
+
L32: none†www.hrw.org】 Dec 13, 2021 — Kenya, with an estimated adult population of
|
| 755 |
+
L33: 27.2 million and a total population of 55 million, has received approximately 23
|
| 756 |
+
L34: million doses as ...
|
| 757 |
+
L35: * 【8†Government gives 20 million a month to get vaccinated; publish_date:
|
| 758 |
+
L36: none†www.bbc.com】 Nov 22, 2021 — Although less than 10% of Kenyans are
|
| 759 |
+
L37: vaccinated, the government wants to avoid a surge over Christmas.
|
| 760 |
+
L38: * 【9†ministry of health kenya covid-19 immunization status ...; publish_date:
|
| 761 |
+
L39: none†www.health.go.ke】 May 15, 2022 — By the end of 2021 Kenya had administered
|
| 762 |
+
L40: 10.1 million doses of 5 types of Covid-19 vaccines. During this period 4.2
|
| 763 |
+
L41: million people were ...</result>
|
| 764 |
+
</function_results>
|
| 765 |
+
|
| 766 |
+
<think>Open result 0.</think>
|
| 767 |
+
|
| 768 |
+
<|DSML|function_calls>
|
| 769 |
+
<|DSML|invoke name="open">
|
| 770 |
+
<|DSML|parameter name="cursor" string="false">13</|DSML|parameter>
|
| 771 |
+
<|DSML|parameter name="id" string="false">0</|DSML|parameter>
|
| 772 |
+
</|DSML|invoke>
|
| 773 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 774 |
+
|
| 775 |
+
<function_results>
|
| 776 |
+
<result>[14] www.worldbank.org (https://www.worldbank.org/en/news/press-release/2021/12/14/kenya-s-economy-is-showing-resilience-as-output-rises-above-pre-pandemic-levels-driven-by-a-rebound-in-the-services-sect)
|
| 777 |
+
**viewing lines [0 - 52] of 61**
|
| 778 |
+
|
| 779 |
+
L0:
|
| 780 |
+
L1: URL: https://www.worldbank.org/en/news/press-release/2021/12/14/kenya-s-economy-
|
| 781 |
+
L2: is-showing-resilience-as-output-rises-above-pre-pandemic-levels-driven-by-a-
|
| 782 |
+
L3: rebound-in-the-services-sect
|
| 783 |
+
L4: NAIROBI, December 14, 2021 — Kenya’s economy has demonstrated resilience to the
|
| 784 |
+
L5: COVID-19 shock, with output in the first half of the year rising above pre-
|
| 785 |
+
L6: pandemic levels. In 2021 as a whole, gross domestic product (GDP) is expected to
|
| 786 |
+
L7: grow by 5%, one of the faster recoveries among Sub-Saharan African countries.
|
| 787 |
+
L8: Overall economic performance is expected to be robust at 4.9% per year in
|
| 788 |
+
L9: 2022-23, similar to the pre-pandemic pace (5% average annual growth from 2010 to
|
| 789 |
+
L10: 2019). According to the 24th edition of the Kenya Economic Update, “From
|
| 790 |
+
L11: Recovery to Better Jobs,” growth has been supported by rebounds in industry and,
|
| 791 |
+
L12: especially, services. Agricultural output, however, fell by 0.5% year on year
|
| 792 |
+
L13: in the first half of 2021 following a particularly strong performance in 2020,
|
| 793 |
+
L14: partly due to below-average rains. Demand-side recovery has been supported by a
|
| 794 |
+
L15: revival in private consumption, against a backdrop of improving employment
|
| 795 |
+
L16: conditions and household incomes. “Kenya’s economy has shown considerable
|
| 796 |
+
L17: resilience to the enormous shock of the pandemic, and this year is expected to
|
| 797 |
+
L18: post one of the stronger growth rebounds in the region thanks to diversified
|
| 798 |
+
L19: sources of growth and sound economic policies and management,” said Keith
|
| 799 |
+
L20: Hansen, World Bank Country Director for Kenya. “However, poverty has increased,
|
| 800 |
+
L21: and the buffers and coping mechanisms of households, firms, and the public
|
| 801 |
+
L22: finances have been depleted.” Economic activity in Kenya has continued to adapt
|
| 802 |
+
L23: to the pandemic and associated restrictions. A mix of containment measures, such
|
| 803 |
+
L24: as a nightly curfew, were in effect through most of 2021, while more
|
| 804 |
+
L25: economically disruptive measures such as lockdowns and travel restrictions were
|
| 805 |
+
L26: phased, limiting the impact on economic activities. The vaccine rollout, which
|
| 806 |
+
L27: had a slow start due to supply constraints, has picked up as new shipments of
|
| 807 |
+
L28: vaccines have arrived, particularly since September. This has supported economic
|
| 808 |
+
L29: recovery and growth through the third quarter of 2021. As of December 5, 2021,
|
| 809 |
+
L30: Kenya had received a total of 16,201,670 vaccines, with 7,583,134 administered.
|
| 810 |
+
L31: While vaccine acceptance is reportedly high there is still a long way to go
|
| 811 |
+
L32: towards the government’s target of fully inoculating the adult population of
|
| 812 |
+
L33: about 30 million by the end of 2022.As of December 6, 2021, about 10% of adults
|
| 813 |
+
L34: (2.9 million people) had been fully vaccinated while another 16% (4.9 million
|
| 814 |
+
L35: people) had received their first dose. The report also projects robust growth in
|
| 815 |
+
L36: the medium-term. This outlook takes into account that some sub-sectors, such as
|
| 816 |
+
L37: education, have bounced back strongly, but others such as international
|
| 817 |
+
L38: tourism, have only partially and face a much more protracted recovery. The
|
| 818 |
+
L39: anticipated further recovery of hotels and restaurants, trade, transport, and
|
| 819 |
+
L40: other services, depends on substantial vaccination progress to help prevent new
|
| 820 |
+
L41: waves of infections and associated containment measures. “Recent economic
|
| 821 |
+
L42: performance has been strong and the outlook is positive, but in Kenya, as
|
| 822 |
+
L43: everywhere, the future course of the pandemic remains a major source of
|
| 823 |
+
L44: uncertainty, said Alex Sienaert, Senior Economist for Kenya. “To support further
|
| 824 |
+
L45: recovery, reduce debt distress risks, and rebuild space for social and
|
| 825 |
+
L46: development spending, it is critical that Kenya continues to implement medium-
|
| 826 |
+
L47: term fiscal consolidation plans.” In addition to pandemic-related risks to the
|
| 827 |
+
L48: outlook, a second key domestic risk factor stems from the drought conditions
|
| 828 |
+
L49: which are affecting parts of the country and already causing severe hardship.
|
| 829 |
+
L50: Should the drought intensify or spread, this would weigh on the near-term
|
| 830 |
+
L51: economic outlook. Weaker global growth, higher-than-anticipated energy prices,
|
| 831 |
+
L52: and tighter external financing conditions are the primary external risks. As </result>
|
| 832 |
+
</function_results>
|
| 833 |
+
|
| 834 |
+
<think>Thus first clue confirmed.
|
| 835 |
+
|
| 836 |
+
Second clue: Defenders of Wildlife 2021 annual report. Confirmed.
|
| 837 |
+
|
| 838 |
+
Third clue: Defenders of Wildlife 2022 annual report. Confirmed.
|
| 839 |
+
|
| 840 |
+
Thus the answer is Terry C. Pelster.
|
| 841 |
+
|
| 842 |
+
But let's verify that the 2022 annual report indeed shows "Contributed services 10%". We saw that. Also confirm that 2021 report shows 12%. We saw that.
|
| 843 |
+
|
| 844 |
+
Thus the question: "Who was the emeritus board member that year?" Refers to 2022. Answer: Terry C. Pelster.
|
| 845 |
+
|
| 846 |
+
However, the question might be asking for the emeritus board member in the 2021 report? Let's read the question carefully:
|
| 847 |
+
|
| 848 |
+
"In a year before 2023, between December 1 and 15 (inclusive), a press release reported that as of the 5th of that month, a country had received a total of 16,201,670 vaccine doses, with 7,583,134 administered. That same year, a company's annual report revealed that its nearly 2.2 million members and supporters contributed over $49 million, with 12% of total revenue coming from contributed services. The following year, the annual report stated that the organization had played a role in rescinding a previous administration’s plan to open most of the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas drilling and that contributed services had decreased by 2% to 10%. Who was the emeritus board member that year? Name only, no titles."
|
| 849 |
+
|
| 850 |
+
The phrase "that year" could refer to "the following year" i.e., the year of the annual report that mentioned the rescinded plan. Or could refer to "that same year" (the year of the press release and the first annual report). However, the phrase "that year" appears at the end: "Who was the emeritus board member that year?" It likely refers to the year of the annual report that is being discussed in the preceding sentence. The preceding sentence talks about the following year's annual report. So indeed "that year" is the following year (2022).
|
| 851 |
+
|
| 852 |
+
Thus answer: Terry C. Pelster.
|
| 853 |
+
|
| 854 |
+
But to be thorough, we should check the 2022 annual report for any other emeritus board members. The search only showed "BOARD EMERITUS Terry C. Pelster, Esq." Maybe there are multiple emeritus board members. But likely only one.
|
| 855 |
+
|
| 856 |
+
Check the 2021 annual report for emeritus board member. It also shows Terry C. Pelster. So maybe the question is asking for the emeritus board member in the 2021 report. But why would they ask that? The question is about connecting the clues to identify the organization and then find the emeritus board member. The clues point to Defenders of Wildlife. The question likely asks for the emeritus board member as of the 2022 report.
|
| 857 |
+
|
| 858 |
+
Nevertheless, we should confirm that the 2022 report is indeed the one that mentions the rescinded plan. We saw that. Also confirm that contributed services decreased from 12% to 10%. We saw that.
|
| 859 |
+
|
| 860 |
+
Thus answer is Terry C. Pelster.
|
| 861 |
+
|
| 862 |
+
But let's search for "Defenders of Wildlife emeritus board member 2022 Terry Pelster".</think>
|
| 863 |
+
|
| 864 |
+
<|DSML|function_calls>
|
| 865 |
+
<|DSML|invoke name="search">
|
| 866 |
+
<|DSML|parameter name="query" string="true">Terry C. Pelster Defenders of Wildlife emeritus board member</|DSML|parameter>
|
| 867 |
+
<|DSML|parameter name="topn" string="false">10</|DSML|parameter>
|
| 868 |
+
<|DSML|parameter name="source" string="true">web</|DSML|parameter>
|
| 869 |
+
</|DSML|invoke>
|
| 870 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 871 |
+
|
| 872 |
+
<function_results>
|
| 873 |
+
<result>[15] Terry C. Pelster Defenders of Wildlife emeritus board member (Search_Results/Terry C. Pelster Defenders of Wildlife emeritus board member)
|
| 874 |
+
**viewing lines [0 - 31] of 31**
|
| 875 |
+
|
| 876 |
+
L0:
|
| 877 |
+
L1: URL: Search_Results/Terry C. Pelster Defenders of Wildlife emeritus board member
|
| 878 |
+
L2: # Search Results
|
| 879 |
+
L3:
|
| 880 |
+
L4: * 【0†2024 impact report; publish_date: none†defenders.org】 Terry Root, Ph.D.
|
| 881 |
+
L5: New Mexico. Thomas D. Sisk, Ph.D. British Columbia, Canada. BOARD EMERITUS.
|
| 882 |
+
L6: Terry C. Pelster, Esq. New York. SCIENCE ADVISORS. Leah Gerber, Ph ...
|
| 883 |
+
L7: * 【1†Defenders of Wildlife; publish_date: none†www.wrongkindofgreen.org】
|
| 884 |
+
L8: Directors ; Victor M. Sher*, Chair – California ; Terry C. Pelster*, Vice Chair
|
| 885 |
+
L9: – New York ; Richard Kopcho*, Treasurer – California ; Adelaide P. Gomer*,
|
| 886 |
+
L10: Secretary ...
|
| 887 |
+
L11: * 【2†Exhibit 12; publish_date: none†www.uschamber.com】 DECLARATION OF TERRY
|
| 888 |
+
L12: PELSTER. I, Terry C. Pelster, declare as follows: 1. I am a current member of
|
| 889 |
+
L13: Defenders of Wildlife (“Defenders”) and have been a member.
|
| 890 |
+
L14: * 【3†2020 ANNUAL REPORT; publish_date: none†defenders.org】 Terry L. Root.
|
| 891 |
+
L15: Florida. BOARD. EMERITUS. Terry C. Pelster. New York. Alan Steinberg. Florida.
|
| 892 |
+
L16: SCIENCE. ADVISORS. Gabriela Chavarria,. Ph.D. Denver Museum of.
|
| 893 |
+
L17: * 【4†2019 Annual Report; publish_date: none†defenders.org】 BOARD EMERITUS.
|
| 894 |
+
L18: Terry C. Pelster. New York. Alan Steinberg. Florida. SCIENCE ADVISORS. Leah
|
| 895 |
+
L19: Gerber, Ph.D. Arizona State University. Kathayoon Khalil, Ph.D.
|
| 896 |
+
L20: * 【5†annual report; publish_date: none†defenders.org】 * Executive Committee
|
| 897 |
+
L21: member. BoARD EMERITuS. Terry C. Pelster. New York. Alan Steinberg. Florida.
|
| 898 |
+
L22: PRESIDENT. EMERITuS. Rodger Schlickeisen. Virginia. SCIENCE ...
|
| 899 |
+
L23: * 【6†BEING THERE FOR BELUGAS; publish_date: none†wendeenicole.com】 Mar 2, 2023
|
| 900 |
+
L24: — Defenders of Wildlife is a national, nonprofit member- ship ... Terry C.
|
| 901 |
+
L25: Pelster, Esq. New York. *Executive Committee member outfront.
|
| 902 |
+
L26: * 【7†Annual Reports; publish_date: none†www.annualreports.com】 WAYS TO GIVE
|
| 903 |
+
L27: There are many ways to support Defenders of Wildlife and protect our imperiled
|
| 904 |
+
L28: wildlife. ... Terry C. Pelster. New York. Alan Steinberg. Florida.
|
| 905 |
+
L29: * 【8†2014 Annual Report; publish_date: none†defenders.org】 BOARD OF DIRECTORS
|
| 906 |
+
L30: defenders of wildlife is a national, nonprofit ... BOARD EMERITUS. Terry C.
|
| 907 |
+
L31: Pelster. New York. Alan Steinberg. Florida. Page 3. PO.</result>
|
| 908 |
+
</function_results>
|
| 909 |
+
|
| 910 |
+
<think>Thus Terry C. Pelster is indeed the emeritus board member.
|
| 911 |
+
|
| 912 |
+
Now the question might want just "Terry C. Pelster". Or maybe "Terry Pelster". Or "Terry C. Pelster, Esq." but instructions say "Name only, no titles." So likely "Terry C. Pelster". However, maybe they want "Terry Pelster". Better to include full name as listed: "Terry C. Pelster".
|
| 913 |
+
|
| 914 |
+
Let's read the question again: "Who was the emeritus board member that year? Name only, no titles." So we should answer just the name, no "Esq." or "Board Emeritus". So "Terry C. Pelster". Or maybe "Terry Pelster". But the document shows "Terry C. Pelster, Esq." So the name is "Terry C. Pelster".
|
| 915 |
+
|
| 916 |
+
Better to verify that the 2022 annual report indeed lists "BOARD EMERITUS Terry C. Pelster, Esq." We saw that line.
|
| 917 |
+
|
| 918 |
+
Thus answer: Terry C. Pelster.
|
| 919 |
+
|
| 920 |
+
But let's double-check that the question might refer to the 2021 annual report. The phrase "that year" could be ambiguous. Let's parse the timeline:
|
| 921 |
+
|
| 922 |
+
- Year 1: 2021. Press release in Dec 2021 about Kenya vaccine doses. Same year (2021) annual report of Defenders of Wildlife shows 12% contributed services.
|
| 923 |
+
|
| 924 |
+
- Year 2: 2022. Annual report mentions rescinded plan and contributed services decreased to 10%.
|
| 925 |
+
|
| 926 |
+
The question says "The following year, the annual report stated that the organization had played a role in rescinding a previous administration’s plan ... and that contributed services had decreased by 2% to 10%." This is year 2.
|
| 927 |
+
|
| 928 |
+
Then asks "Who was the emeritus board member that year?" That likely refers to year 2.
|
| 929 |
+
|
| 930 |
+
Thus answer: Terry C. Pelster.
|
| 931 |
+
|
| 932 |
+
However, perhaps the emeritus board member changed between 2021 and 2022. We need to check 2022 annual report for any other emeritus board member. We saw only Terry C. Pelster. Also check 2021 annual report: same. So likely unchanged.
|
| 933 |
+
|
| 934 |
+
Thus answer is Terry C. Pelster.
|
| 935 |
+
|
| 936 |
+
Nevertheless, we should confirm that the 2022 annual report is indeed the one that includes the phrase "BLM rescinded the previous administration’s plan that opened most of the 22 million acres of the National Petroleum Reserve in Alaska to oil and gas drilling". We saw that in line 200-202.
|
| 937 |
+
|
| 938 |
+
Thus answer is Terry C. Pelster.
|
| 939 |
+
|
| 940 |
+
Now we need to provide the answer in the final message. Only the name.
|
| 941 |
+
|
| 942 |
+
Thus final answer: Terry C. Pelster.
|
| 943 |
+
|
| 944 |
+
But let's be thorough and search for "Defenders of Wildlife 2022 annual report contributed services 10%".</think>
|
| 945 |
+
|
| 946 |
+
<|DSML|function_calls>
|
| 947 |
+
<|DSML|invoke name="find">
|
| 948 |
+
<|DSML|parameter name="cursor" string="false">8</|DSML|parameter>
|
| 949 |
+
<|DSML|parameter name="pattern" string="true">Contributed services</|DSML|parameter>
|
| 950 |
+
</|DSML|invoke>
|
| 951 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 952 |
+
|
| 953 |
+
<function_results>
|
| 954 |
+
<result>[16] Find results for text: `contributed services` in `www.annualreports.com` (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2022.pdf/find?pattern=contributed services)
|
| 955 |
+
**viewing lines [0 - 10] of 10**
|
| 956 |
+
|
| 957 |
+
L0: # 【0†match at L222】
|
| 958 |
+
L1: income $744 Contributed services $5,047 Total Revenue $41,170 USES OF FUNDS
|
| 959 |
+
L2: Biodiversity conservation $18,970 Constituency mobilization $16,528 Fundraising
|
| 960 |
+
L3: $1,029 Management and general $6,354 Total Expenses $42,881 Change in net assets
|
| 961 |
+
L4: (-$1,711) Net assets, start of year $45,144 Net Assets, End of the Year $43,433
|
| 962 |
+
L5:
|
| 963 |
+
L6: # 【1†match at L227】
|
| 964 |
+
L7: Contributed services 10% Royalties and other income 2% Bequests, trusts and
|
| 965 |
+
L8: split interests 29% TOTAL REVENUE Income from investments -15% Program and
|
| 966 |
+
L9: support services 98% USE OF FUNDS Fundraising 2% ===== Page 13 =====
|
| 967 |
+
L10: DEFENDERS.ORG 13 ===== Page 14 ===== BOARD OF DIRECTORS John Dayton, Esq.* Chair</result>
|
| 968 |
+
</function_results>
|
| 969 |
+
|
| 970 |
+
<think>Thus confirmed.
|
| 971 |
+
|
| 972 |
+
Now we should verify that the 2021 annual report shows contributed services 12%.</think>
|
| 973 |
+
|
| 974 |
+
<|DSML|function_calls>
|
| 975 |
+
<|DSML|invoke name="find">
|
| 976 |
+
<|DSML|parameter name="cursor" string="false">4</|DSML|parameter>
|
| 977 |
+
<|DSML|parameter name="pattern" string="true">Contributed services</|DSML|parameter>
|
| 978 |
+
</|DSML|invoke>
|
| 979 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 980 |
+
|
| 981 |
+
<function_results>
|
| 982 |
+
<result>[17] Find results for text: `contributed services` in `www.annualreports.com` (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2021.pdf/find?pattern=contributed services)
|
| 983 |
+
**viewing lines [0 - 4] of 4**
|
| 984 |
+
|
| 985 |
+
L0: # 【0†match at L194】
|
| 986 |
+
L1: $3,354 Royalties and other income $3,576 Contributed services $6,140 Total
|
| 987 |
+
L2: Revenue $49,819 USES OF FUNDS Biodiversity conservation $22,420 Constituency
|
| 988 |
+
L3: mobilization $16,324 Fundraising $1,211 Management and general $5,865 Total
|
| 989 |
+
L4: Expenses $45,820 Change in net assets $3,999 Net assets, start of year $41,145 </result>
|
| 990 |
+
</function_results>
|
| 991 |
+
|
| 992 |
+
<think>Open around L190-200 to see percentage.</think>
|
| 993 |
+
|
| 994 |
+
<|DSML|function_calls>
|
| 995 |
+
<|DSML|invoke name="open">
|
| 996 |
+
<|DSML|parameter name="cursor" string="false">4</|DSML|parameter>
|
| 997 |
+
<|DSML|parameter name="loc" string="false">185</|DSML|parameter>
|
| 998 |
+
</|DSML|invoke>
|
| 999 |
+
</|DSML|function_calls><|end▁of▁sentence|>
|
| 1000 |
+
|
| 1001 |
+
<function_results>
|
| 1002 |
+
<result>[18] www.annualreports.com (https://www.annualreports.com/HostedData/AnnualReportArchive/d/defenders-wildlife_2021.pdf)
|
| 1003 |
+
**viewing lines [185 - 232] of 261**
|
| 1004 |
+
|
| 1005 |
+
L185: devastating water pollution that is killing the seagrass and causing manatees to
|
| 1006 |
+
L186: starve. DAVID TES | SAM FRENZY DRAW DEFENDERS.ORG 11 ===== Page 12 ===== In
|
| 1007 |
+
L187: 2021, Defenders of Wildlife’s nearly 2.2 million members and supporters
|
| 1008 |
+
L188: contributed more than $49 million for wildlife and wildlife habitat. This figure
|
| 1009 |
+
L189: includes all those who generously donated their time and expertise. The
|
| 1010 |
+
L190: steadfast support of our donors allows Defenders to sustain our program and
|
| 1011 |
+
L191: public education efforts in the field, the courts and on Capitol Hill. 2021
|
| 1012 |
+
L192: SOURCES OF FUNDS Grants and contributions $29,057 Bequests, trusts and split
|
| 1013 |
+
L193: interests $7,692 Income from investments, annuity reserve funds and trusts
|
| 1014 |
+
L194: $3,354 Royalties and other income $3,576 Contributed services $6,140 Total
|
| 1015 |
+
L195: Revenue $49,819 USES OF FUNDS Biodiversity conservation $22,420 Constituency
|
| 1016 |
+
L196: mobilization $16,324 Fundraising $1,211 Management and general $5,865 Total
|
| 1017 |
+
L197: Expenses $45,820 Change in net assets $3,999 Net assets, start of year $41,145
|
| 1018 |
+
L198: Net Assets, End of the Year $45,144 Dollars are in thousands. 12 DEFENDERS OF
|
| 1019 |
+
L199: WILDLIFE Grants and contributions 58% Income from investments 7% Requests,
|
| 1020 |
+
L200: trusts and split interests 15% Royalties and other income 7% Contributed
|
| 1021 |
+
L201: services 12% Program and support services 97% Fundraising 3% ===== Page 13 =====
|
| 1022 |
+
L202: DEFENDERS.ORG 13 ===== Page 14 ===== John Dayton, Esq.* Chair Texas Sheryl
|
| 1023 |
+
L203: Sachs* Vice Chair Connecticut Whitfield Bailey* Secretary Tennessee Mark Caylor*
|
| 1024 |
+
L204: Treasurer District of Columbia Sylvia Baca* California Donald Barry, Esq.
|
| 1025 |
+
L205: Oregon Dinah Bear, Esq. Arizona Kim O’Keefe Beck, Ph.D California Gabriela
|
| 1026 |
+
L206: Chavarria, Ph.D Washington Jamie Rappaport Clark* President & CEO Virginia
|
| 1027 |
+
L207: Caroline D. Gabel Maryland Keith M. Harper, Esq. Maryland John Donovan, Esq.
|
| 1028 |
+
L208: Montana and California James M. Hecker, Esq. Virginia Judith Ponsikoff, Ph.D*
|
| 1029 |
+
L209: California Terry L. Root, Ph.D Florida BOARD EMERITUS Terry C. Pelster, Esq. New
|
| 1030 |
+
L210: York *Executive Committee member* ST A F F & A D V I S O R S SCIENCE ADVISORS
|
| 1031 |
+
L211: Gabriela Chavarria, Ph.D Burke Museum, University of Washington Leah Gerber,
|
| 1032 |
+
L212: Ph.D Arizona State University Kathayoon Khalil, Ph.D Oregon Zoo Rurik List, Ph.D
|
| 1033 |
+
L213: Universidad Autónoma Metropolitana-Lerma Barry Noon, Ph.D Colorado State
|
| 1034 |
+
L214: University Terry L. Root, Ph.D Stanford University Mark Schwartz, Ph.D
|
| 1035 |
+
L215: University of California-Davis David S. Wilcox, Ph.D Princeton University Rae
|
| 1036 |
+
L216: Wynn-Grant, Ph.D National Geographic Society SENIOR STAFF Jamie Rappaport Clark
|
| 1037 |
+
L217: President & CEO Thu Pham Chief of Staff Renee Stone Senior Vice President,
|
| 1038 |
+
L218: Conservation Programs & General Counsel James Stefan Senior Vice President,
|
| 1039 |
+
L219: Operations Matt Braughler Vice President, Philanthropy Rachel Brittin Vice
|
| 1040 |
+
L220: President, Communications Shawn Cantrell Vice President, Field Conservation
|
| 1041 |
+
L221: Programs Robert L. Dewey Vice President, Government Relations & External Affairs
|
| 1042 |
+
L222: Monica Goldberg Vice President, Landscape Conservation Sharon Morris-Smith Vice
|
| 1043 |
+
L223: President of Human Resources Elizabeth Nichols Vice President, Finance/CFO
|
| 1044 |
+
L224: Anthony Pegues Vice President, Diversity, Equity, Inclusion, Justice Lindsay
|
| 1045 |
+
L225: Rosa, Ph.D Director, Center for Conservation Innovation Michael P. Senatore Vice
|
| 1046 |
+
L226: President, Conservation Law Brandace Swimley Vice President, Integrated
|
| 1047 |
+
L227: Marketing 14 DEFENDERS OF WILDLIFE ===== Page 15 ===== THERE ARE MANY WAYS TO
|
| 1048 |
+
L228: SUPPORT DEFENDERS OF WILDLIFE and protect our imperiled wildlife. To learn more
|
| 1049 |
+
L229: or donate, contact us at 1-800-385-9712, visit defenders.org/donate or choose
|
| 1050 |
+
L230: one of the following options. ➤ Transfer appreciated assets directly to
|
| 1051 |
+
L231: Defenders and maximize potential tax benefits. Defenders.org/donate-stocks-help-
|
| 1052 |
+
L232: save-wildlife ➤ Become a Leadership Council member with a single donation of </result>
|
| 1053 |
+
</function_results>
|
| 1054 |
+
|
| 1055 |
+
<think>Thus everything matches.
|
| 1056 |
+
|
| 1057 |
+
Thus answer: Terry C. Pelster.
|
| 1058 |
+
|
| 1059 |
+
Now we need to output only the name.
|
| 1060 |
+
|
| 1061 |
+
Thus final answer: Terry C. Pelster.
|
| 1062 |
+
|
| 1063 |
+
But perhaps the question expects "Terry Pelster". However, the document includes middle initial "C." It might be better to include the full name as listed: "Terry C. Pelster". The instruction "Name only, no titles" suggests we should not include "Esq." or "Board Emeritus". But including middle initial is likely okay.
|
| 1064 |
+
|
| 1065 |
+
To be safe, we could output "Terry C. Pelster". Let's see similar puzzles: often they expect the full name as appears in the document.
|
| 1066 |
+
|
| 1067 |
+
Thus answer: Terry C. Pelster.
|
| 1068 |
+
|
| 1069 |
+
Now we will provide final answer.</think>Terry C. Pelster<|end▁of▁sentence|>
|
generation_config.json
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"_from_model_config": true,
|
| 3 |
+
"transformers_version": "4.57.1"
|
| 4 |
+
}
|
inference/README.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# DeepSeek V3.2
|
| 2 |
+
|
| 3 |
+
First convert huggingface model weights to the the format required by our inference demo. Set `MP` to match your available GPU count:
|
| 4 |
+
```bash
|
| 5 |
+
cd inference
|
| 6 |
+
export EXPERTS=256
|
| 7 |
+
python convert.py --hf-ckpt-path ${HF_CKPT_PATH} --save-path ${SAVE_PATH} --n-experts ${EXPERTS} --model-parallel ${MP}
|
| 8 |
+
```
|
| 9 |
+
|
| 10 |
+
Launch the interactive chat interface and start exploring DeepSeek's capabilities:
|
| 11 |
+
```bash
|
| 12 |
+
export CONFIG=config_671B_v3.2.json
|
| 13 |
+
torchrun --nproc-per-node ${MP} generate.py --ckpt-path ${SAVE_PATH} --config ${CONFIG} --interactive
|
| 14 |
+
```
|
inference/config_671B_v3.2.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"vocab_size": 129280,
|
| 3 |
+
"dim": 7168,
|
| 4 |
+
"inter_dim": 18432,
|
| 5 |
+
"moe_inter_dim": 2048,
|
| 6 |
+
"n_layers": 61,
|
| 7 |
+
"n_dense_layers": 3,
|
| 8 |
+
"n_heads": 128,
|
| 9 |
+
"n_routed_experts": 256,
|
| 10 |
+
"n_shared_experts": 1,
|
| 11 |
+
"n_activated_experts": 8,
|
| 12 |
+
"n_expert_groups": 8,
|
| 13 |
+
"n_limited_groups": 4,
|
| 14 |
+
"route_scale": 2.5,
|
| 15 |
+
"score_func": "sigmoid",
|
| 16 |
+
"q_lora_rank": 1536,
|
| 17 |
+
"kv_lora_rank": 512,
|
| 18 |
+
"qk_nope_head_dim": 128,
|
| 19 |
+
"qk_rope_head_dim": 64,
|
| 20 |
+
"v_head_dim": 128,
|
| 21 |
+
"dtype": "fp8",
|
| 22 |
+
"scale_fmt": "ue8m0",
|
| 23 |
+
"index_n_heads": 64,
|
| 24 |
+
"index_head_dim": 128,
|
| 25 |
+
"index_topk": 2048
|
| 26 |
+
}
|
inference/convert.py
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import shutil
|
| 3 |
+
from argparse import ArgumentParser
|
| 4 |
+
from glob import glob
|
| 5 |
+
from tqdm import tqdm, trange
|
| 6 |
+
|
| 7 |
+
import torch
|
| 8 |
+
from safetensors.torch import safe_open, save_file
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
mapping = {
|
| 12 |
+
"embed_tokens": ("embed", 0),
|
| 13 |
+
"input_layernorm": ("attn_norm", None),
|
| 14 |
+
"post_attention_layernorm": ("ffn_norm", None),
|
| 15 |
+
"q_proj": ("wq", 0),
|
| 16 |
+
"q_a_proj": ("wq_a", None),
|
| 17 |
+
"q_a_layernorm": ("q_norm", None),
|
| 18 |
+
"q_b_proj": ("wq_b", 0),
|
| 19 |
+
"kv_a_proj_with_mqa": ("wkv_a", None),
|
| 20 |
+
"kv_a_layernorm": ("kv_norm", None),
|
| 21 |
+
"kv_b_proj": ("wkv_b", 0),
|
| 22 |
+
"o_proj": ("wo", 1),
|
| 23 |
+
"gate": ("gate", None),
|
| 24 |
+
"gate_proj": ("w1", 0),
|
| 25 |
+
"down_proj": ("w2", 1),
|
| 26 |
+
"up_proj": ("w3", 0),
|
| 27 |
+
"norm": ("norm", None),
|
| 28 |
+
"lm_head": ("head", 0),
|
| 29 |
+
"scale": ("scale", None),
|
| 30 |
+
"wq_b": ("wq_b", None),
|
| 31 |
+
"wk": ("wk", None),
|
| 32 |
+
"k_norm": ("k_norm", None),
|
| 33 |
+
"weights_proj": ("weights_proj", None),
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def main(hf_ckpt_path, save_path, n_experts, mp):
|
| 38 |
+
"""
|
| 39 |
+
Converts and saves model checkpoint files into a specified format.
|
| 40 |
+
|
| 41 |
+
Args:
|
| 42 |
+
hf_ckpt_path (str): Path to the directory containing the input checkpoint files.
|
| 43 |
+
save_path (str): Path to the directory where the converted checkpoint files will be saved.
|
| 44 |
+
n_experts (int): Total number of experts in the model.
|
| 45 |
+
mp (int): Model parallelism factor.
|
| 46 |
+
|
| 47 |
+
Returns:
|
| 48 |
+
None
|
| 49 |
+
"""
|
| 50 |
+
torch.set_num_threads(8)
|
| 51 |
+
n_local_experts = n_experts // mp
|
| 52 |
+
state_dicts = [{} for _ in range(mp)]
|
| 53 |
+
|
| 54 |
+
for file_path in tqdm(glob(os.path.join(hf_ckpt_path, "*.safetensors"))):
|
| 55 |
+
with safe_open(file_path, framework="pt", device="cpu") as f:
|
| 56 |
+
for name in f.keys():
|
| 57 |
+
if "model.layers.61" in name:
|
| 58 |
+
continue
|
| 59 |
+
param: torch.Tensor = f.get_tensor(name)
|
| 60 |
+
if name.startswith("model."):
|
| 61 |
+
name = name[len("model."):]
|
| 62 |
+
name = name.replace("self_attn", "attn")
|
| 63 |
+
name = name.replace("mlp", "ffn")
|
| 64 |
+
name = name.replace("weight_scale_inv", "scale")
|
| 65 |
+
name = name.replace("e_score_correction_bias", "bias")
|
| 66 |
+
key = name.split(".")[-2]
|
| 67 |
+
assert key in mapping, f"Key {key} not found in mapping"
|
| 68 |
+
new_key, dim = mapping[key]
|
| 69 |
+
name = name.replace(key, new_key)
|
| 70 |
+
for i in range(mp):
|
| 71 |
+
new_param = param
|
| 72 |
+
if "experts" in name and "shared_experts" not in name:
|
| 73 |
+
idx = int(name.split(".")[-3])
|
| 74 |
+
if idx < i * n_local_experts or idx >= (i + 1) * n_local_experts:
|
| 75 |
+
continue
|
| 76 |
+
elif dim is not None:
|
| 77 |
+
assert param.size(dim) % mp == 0, f"Dimension {dim} must be divisible by {mp}"
|
| 78 |
+
shard_size = param.size(dim) // mp
|
| 79 |
+
new_param = param.narrow(dim, i * shard_size, shard_size).contiguous()
|
| 80 |
+
state_dicts[i][name] = new_param
|
| 81 |
+
|
| 82 |
+
os.makedirs(save_path, exist_ok=True)
|
| 83 |
+
|
| 84 |
+
for i in trange(mp):
|
| 85 |
+
save_file(state_dicts[i], os.path.join(save_path, f"model{i}-mp{mp}.safetensors"))
|
| 86 |
+
|
| 87 |
+
for file_path in glob(os.path.join(hf_ckpt_path, "*token*")):
|
| 88 |
+
new_file_path = os.path.join(save_path, os.path.basename(file_path))
|
| 89 |
+
shutil.copyfile(file_path, new_file_path)
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
if __name__ == "__main__":
|
| 93 |
+
parser = ArgumentParser()
|
| 94 |
+
parser.add_argument("--hf-ckpt-path", type=str, required=True)
|
| 95 |
+
parser.add_argument("--save-path", type=str, required=True)
|
| 96 |
+
parser.add_argument("--n-experts", type=int, required=True)
|
| 97 |
+
parser.add_argument("--model-parallel", type=int, required=True)
|
| 98 |
+
args = parser.parse_args()
|
| 99 |
+
assert args.n_experts % args.model_parallel == 0, "Number of experts must be divisible by model parallelism"
|
| 100 |
+
main(args.hf_ckpt_path, args.save_path, args.n_experts, args.model_parallel)
|
inference/generate.py
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import json
|
| 3 |
+
from argparse import ArgumentParser
|
| 4 |
+
from typing import List
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
import torch.distributed as dist
|
| 8 |
+
from transformers import AutoTokenizer
|
| 9 |
+
from safetensors.torch import load_model
|
| 10 |
+
|
| 11 |
+
from model import Transformer, ModelArgs
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
def sample(logits, temperature: float = 1.0):
|
| 15 |
+
"""
|
| 16 |
+
Samples a token from the logits using temperature scaling.
|
| 17 |
+
|
| 18 |
+
Args:
|
| 19 |
+
logits (torch.Tensor): The logits tensor for token predictions.
|
| 20 |
+
temperature (float, optional): Temperature for scaling logits. Defaults to 1.0.
|
| 21 |
+
|
| 22 |
+
Returns:
|
| 23 |
+
torch.Tensor: The sampled token.
|
| 24 |
+
"""
|
| 25 |
+
logits = logits / max(temperature, 1e-5)
|
| 26 |
+
probs = torch.softmax(logits, dim=-1, dtype=torch.float32)
|
| 27 |
+
return probs.div_(torch.empty_like(probs).exponential_(1)).argmax(dim=-1)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
@torch.inference_mode()
|
| 31 |
+
def generate(
|
| 32 |
+
model: Transformer,
|
| 33 |
+
prompt_tokens: List[List[int]],
|
| 34 |
+
max_new_tokens: int,
|
| 35 |
+
eos_id: int,
|
| 36 |
+
temperature: float = 1.0
|
| 37 |
+
) -> List[List[int]]:
|
| 38 |
+
"""
|
| 39 |
+
Generates new tokens based on the given prompt tokens using the specified model.
|
| 40 |
+
|
| 41 |
+
Args:
|
| 42 |
+
model (Transformer): The transformer model used for token generation.
|
| 43 |
+
prompt_tokens (List[List[int]]): A list of lists containing the prompt tokens for each sequence.
|
| 44 |
+
max_new_tokens (int): The maximum number of new tokens to generate.
|
| 45 |
+
eos_id (int): The end-of-sequence token ID.
|
| 46 |
+
temperature (float, optional): The temperature value for sampling. Defaults to 1.0.
|
| 47 |
+
|
| 48 |
+
Returns:
|
| 49 |
+
List[List[int]]: A list of lists containing the generated tokens for each sequence.
|
| 50 |
+
"""
|
| 51 |
+
prompt_lens = [len(t) for t in prompt_tokens]
|
| 52 |
+
assert max(prompt_lens) <= model.max_seq_len, f"Prompt length exceeds model maximum sequence length (max_seq_len={model.max_seq_len})"
|
| 53 |
+
total_len = min(model.max_seq_len, max_new_tokens + max(prompt_lens))
|
| 54 |
+
tokens = torch.full((len(prompt_tokens), total_len), -1, dtype=torch.long, device="cuda")
|
| 55 |
+
for i, t in enumerate(prompt_tokens):
|
| 56 |
+
tokens[i, :len(t)] = torch.tensor(t, dtype=torch.long, device="cuda")
|
| 57 |
+
prev_pos = 0
|
| 58 |
+
finished = torch.tensor([False] * len(prompt_tokens), device="cuda")
|
| 59 |
+
prompt_mask = tokens != -1
|
| 60 |
+
for cur_pos in range(min(prompt_lens), total_len):
|
| 61 |
+
logits = model.forward(tokens[:, prev_pos:cur_pos], prev_pos)
|
| 62 |
+
if temperature > 0:
|
| 63 |
+
next_token = sample(logits, temperature)
|
| 64 |
+
else:
|
| 65 |
+
next_token = logits.argmax(dim=-1)
|
| 66 |
+
next_token = torch.where(prompt_mask[:, cur_pos], tokens[:, cur_pos], next_token)
|
| 67 |
+
tokens[:, cur_pos] = next_token
|
| 68 |
+
finished |= torch.logical_and(~prompt_mask[:, cur_pos], next_token == eos_id)
|
| 69 |
+
prev_pos = cur_pos
|
| 70 |
+
if finished.all():
|
| 71 |
+
break
|
| 72 |
+
completion_tokens = []
|
| 73 |
+
for i, toks in enumerate(tokens.tolist()):
|
| 74 |
+
toks = toks[prompt_lens[i]:prompt_lens[i]+max_new_tokens]
|
| 75 |
+
if eos_id in toks:
|
| 76 |
+
toks = toks[:toks.index(eos_id)]
|
| 77 |
+
completion_tokens.append(toks)
|
| 78 |
+
return completion_tokens
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def main(
|
| 82 |
+
ckpt_path: str,
|
| 83 |
+
config: str,
|
| 84 |
+
input_file: str = "",
|
| 85 |
+
interactive: bool = True,
|
| 86 |
+
max_new_tokens: int = 100,
|
| 87 |
+
temperature: float = 1.0,
|
| 88 |
+
) -> None:
|
| 89 |
+
"""
|
| 90 |
+
Main function to load the model and perform interactive or batch text generation.
|
| 91 |
+
|
| 92 |
+
Args:
|
| 93 |
+
ckpt_path (str): Path to the model checkpoint directory.
|
| 94 |
+
config (str): Path to the model configuration file.
|
| 95 |
+
input_file (str, optional): Path to a file containing input prompts. Defaults to "".
|
| 96 |
+
interactive (bool, optional): Whether to run in interactive mode. Defaults to True.
|
| 97 |
+
max_new_tokens (int, optional): Maximum number of new tokens to generate. Defaults to 100.
|
| 98 |
+
temperature (float, optional): Temperature for sampling. Defaults to 1.0.
|
| 99 |
+
"""
|
| 100 |
+
world_size = int(os.getenv("WORLD_SIZE", "1"))
|
| 101 |
+
rank = int(os.getenv("RANK", "0"))
|
| 102 |
+
local_rank = int(os.getenv("LOCAL_RANK", "0"))
|
| 103 |
+
if world_size > 1:
|
| 104 |
+
dist.init_process_group("nccl")
|
| 105 |
+
global print
|
| 106 |
+
if rank != 0:
|
| 107 |
+
print = lambda *_, **__: None
|
| 108 |
+
torch.cuda.set_device(local_rank)
|
| 109 |
+
torch.set_default_dtype(torch.bfloat16)
|
| 110 |
+
torch.set_num_threads(8)
|
| 111 |
+
torch.manual_seed(33377335)
|
| 112 |
+
with open(config) as f:
|
| 113 |
+
args = ModelArgs(**json.load(f))
|
| 114 |
+
print(args)
|
| 115 |
+
with torch.device("cuda"):
|
| 116 |
+
model = Transformer(args)
|
| 117 |
+
tokenizer = AutoTokenizer.from_pretrained(ckpt_path)
|
| 118 |
+
print("load model")
|
| 119 |
+
load_model(model, os.path.join(ckpt_path, f"model{rank}-mp{world_size}.safetensors"))
|
| 120 |
+
print("I'm DeepSeek 👋")
|
| 121 |
+
|
| 122 |
+
if interactive:
|
| 123 |
+
messages = []
|
| 124 |
+
while True:
|
| 125 |
+
if world_size == 1:
|
| 126 |
+
prompt = input(">>> ")
|
| 127 |
+
elif rank == 0:
|
| 128 |
+
prompt = input(">>> ")
|
| 129 |
+
objects = [prompt]
|
| 130 |
+
dist.broadcast_object_list(objects, 0)
|
| 131 |
+
else:
|
| 132 |
+
objects = [None]
|
| 133 |
+
dist.broadcast_object_list(objects, 0)
|
| 134 |
+
prompt = objects[0]
|
| 135 |
+
if prompt == "/exit":
|
| 136 |
+
break
|
| 137 |
+
elif prompt == "/clear":
|
| 138 |
+
messages.clear()
|
| 139 |
+
continue
|
| 140 |
+
messages.append({"role": "user", "content": prompt})
|
| 141 |
+
prompt_tokens = tokenizer.apply_chat_template(messages, add_generation_prompt=True)
|
| 142 |
+
completion_tokens = generate(model, [prompt_tokens], max_new_tokens, tokenizer.eos_token_id, temperature)
|
| 143 |
+
completion = tokenizer.decode(completion_tokens[0], skip_special_tokens=True)
|
| 144 |
+
print(completion)
|
| 145 |
+
messages.append({"role": "assistant", "content": completion})
|
| 146 |
+
else:
|
| 147 |
+
with open(input_file) as f:
|
| 148 |
+
prompts = f.read().split("\n\n")
|
| 149 |
+
assert len(prompts) <= args.max_batch_size, f"Number of prompts exceeds maximum batch size ({args.max_batch_size})"
|
| 150 |
+
prompt_tokens = [tokenizer.apply_chat_template([{"role": "user", "content": prompt}], add_generation_prompt=True) for prompt in prompts]
|
| 151 |
+
completion_tokens = generate(model, prompt_tokens, max_new_tokens, tokenizer.eos_token_id, temperature)
|
| 152 |
+
completions = tokenizer.batch_decode(completion_tokens, skip_special_tokens=True)
|
| 153 |
+
for prompt, completion in zip(prompts, completions):
|
| 154 |
+
print("Prompt:", prompt)
|
| 155 |
+
print("Completion:", completion)
|
| 156 |
+
print()
|
| 157 |
+
|
| 158 |
+
if world_size > 1:
|
| 159 |
+
dist.destroy_process_group()
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
if __name__ == "__main__":
|
| 163 |
+
"""
|
| 164 |
+
Command-line interface for distributed text generation.
|
| 165 |
+
|
| 166 |
+
Arguments:
|
| 167 |
+
--ckpt-path (str): Path to the model checkpoint directory.
|
| 168 |
+
--config (str): Path to the model configuration file.
|
| 169 |
+
--input-file (str, optional): File containing prompts for batch processing.
|
| 170 |
+
--interactive (bool, optional): Enable interactive mode for generating text.
|
| 171 |
+
--max-new-tokens (int, optional): Maximum number of new tokens to generate. Defaults to 200.
|
| 172 |
+
--temperature (float, optional): Temperature for sampling. Defaults to 0.2.
|
| 173 |
+
|
| 174 |
+
Raises:
|
| 175 |
+
AssertionError: If neither input-file nor interactive mode is specified.
|
| 176 |
+
"""
|
| 177 |
+
parser = ArgumentParser()
|
| 178 |
+
parser.add_argument("--ckpt-path", type=str, required=True)
|
| 179 |
+
parser.add_argument("--config", type=str, required=True)
|
| 180 |
+
parser.add_argument("--input-file", type=str, default="")
|
| 181 |
+
parser.add_argument("--interactive", action="store_true")
|
| 182 |
+
parser.add_argument("--max-new-tokens", type=int, default=200)
|
| 183 |
+
parser.add_argument("--temperature", type=float, default=0.6)
|
| 184 |
+
args = parser.parse_args()
|
| 185 |
+
assert args.input_file or args.interactive, "Either input-file or interactive mode must be specified"
|
| 186 |
+
main(args.ckpt_path, args.config, args.input_file, args.interactive, args.max_new_tokens, args.temperature)
|
inference/kernel.py
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
import tilelang
|
| 3 |
+
import tilelang.language as T
|
| 4 |
+
from typing import Tuple, Optional
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
tilelang.set_log_level("WARNING")
|
| 8 |
+
|
| 9 |
+
pass_configs = {
|
| 10 |
+
tilelang.PassConfigKey.TL_DISABLE_WARP_SPECIALIZED: True,
|
| 11 |
+
tilelang.PassConfigKey.TL_DISABLE_TMA_LOWER: True,
|
| 12 |
+
tilelang.PassConfigKey.TL_DISABLE_FAST_MATH: True,
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
FP8 = "float8_e4m3"
|
| 16 |
+
BF16 = "bfloat16"
|
| 17 |
+
FP32 = "float32"
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def fast_log2_ceil(x):
|
| 21 |
+
bits_x = T.reinterpret("uint32", x)
|
| 22 |
+
exp_x = (bits_x >> 23) & 0xFF
|
| 23 |
+
man_bits = bits_x & ((1 << 23) - 1)
|
| 24 |
+
return T.Cast("int32", exp_x - 127 + T.if_then_else(man_bits != 0, 1, 0))
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def fast_pow2(x):
|
| 28 |
+
bits_x = (x + 127) << 23
|
| 29 |
+
return T.reinterpret("float32", bits_x)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def fast_round_scale(amax, fp8_max_inv):
|
| 33 |
+
return fast_pow2(fast_log2_ceil(amax * fp8_max_inv))
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
@tilelang.jit(pass_configs=pass_configs)
|
| 37 |
+
def act_quant_kernel(
|
| 38 |
+
N, in_dtype=BF16, out_dtype=FP8, scale_dtype=FP32, round_scale=False
|
| 39 |
+
):
|
| 40 |
+
M = T.symbolic("M")
|
| 41 |
+
fp8_min = -448.0
|
| 42 |
+
fp8_max = 448.0
|
| 43 |
+
fp8_max_inv = 1 / fp8_max
|
| 44 |
+
num_stages = 0 if round_scale else 2
|
| 45 |
+
blk_m = 32
|
| 46 |
+
group_size = 128
|
| 47 |
+
|
| 48 |
+
@T.prim_func
|
| 49 |
+
def act_quant_kernel_(
|
| 50 |
+
X: T.Tensor[(M, N), in_dtype],
|
| 51 |
+
Y: T.Tensor[(M, N), out_dtype],
|
| 52 |
+
S: T.Tensor[(M, T.ceildiv(N, group_size)), scale_dtype],
|
| 53 |
+
):
|
| 54 |
+
with T.Kernel(T.ceildiv(M, blk_m), T.ceildiv(N, group_size), threads=128) as (
|
| 55 |
+
pid_m,
|
| 56 |
+
pid_n,
|
| 57 |
+
):
|
| 58 |
+
x_shared = T.alloc_shared((blk_m, group_size), in_dtype)
|
| 59 |
+
x_local = T.alloc_fragment((blk_m, group_size), in_dtype)
|
| 60 |
+
amax_local = T.alloc_fragment((blk_m,), scale_dtype)
|
| 61 |
+
s_local = T.alloc_fragment((blk_m,), scale_dtype)
|
| 62 |
+
y_local = T.alloc_fragment((blk_m, group_size), out_dtype)
|
| 63 |
+
y_shared = T.alloc_shared((blk_m, group_size), out_dtype)
|
| 64 |
+
|
| 65 |
+
for _ in T.Pipelined(1, num_stages=num_stages):
|
| 66 |
+
T.copy(X[pid_m * blk_m, pid_n * group_size], x_shared)
|
| 67 |
+
T.copy(x_shared, x_local)
|
| 68 |
+
T.reduce_absmax(x_local, amax_local, dim=1)
|
| 69 |
+
for i in T.Parallel(blk_m):
|
| 70 |
+
amax_local[i] = T.max(amax_local[i], 1e-4)
|
| 71 |
+
if round_scale:
|
| 72 |
+
s_local[i] = fast_round_scale(amax_local[i], fp8_max_inv)
|
| 73 |
+
else:
|
| 74 |
+
s_local[i] = amax_local[i] * fp8_max_inv
|
| 75 |
+
for i, j in T.Parallel(blk_m, group_size):
|
| 76 |
+
y_local[i, j] = T.clamp(
|
| 77 |
+
x_local[i, j] / s_local[i], fp8_min, fp8_max
|
| 78 |
+
)
|
| 79 |
+
for i in T.Parallel(blk_m):
|
| 80 |
+
S[pid_m * blk_m + i, pid_n] = s_local[i]
|
| 81 |
+
T.copy(y_local, y_shared)
|
| 82 |
+
T.copy(y_shared, Y[pid_m * blk_m, pid_n * group_size])
|
| 83 |
+
|
| 84 |
+
return act_quant_kernel_
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def act_quant(
|
| 88 |
+
x: torch.Tensor, block_size: int = 128, scale_fmt: Optional[str] = None
|
| 89 |
+
) -> Tuple[torch.Tensor, torch.Tensor]:
|
| 90 |
+
"""
|
| 91 |
+
Quantizes the input tensor `x` using block-wise quantization.
|
| 92 |
+
|
| 93 |
+
Args:
|
| 94 |
+
x (torch.Tensor): The input tensor to be quantized. Must be contiguous and its last dimension size must be divisible by `block_size`.
|
| 95 |
+
block_size (int, optional): The size of the blocks to be used for quantization. Default is 128.
|
| 96 |
+
scale_fmt (Optional[str], optional): The format of the scale. Default is None.
|
| 97 |
+
Returns:
|
| 98 |
+
Tuple[torch.Tensor, torch.Tensor]: A tuple containing:
|
| 99 |
+
- The quantized tensor with dtype `torch.float8_e4m3fn`.
|
| 100 |
+
- A tensor of scaling factors with dtype `torch.float32`.
|
| 101 |
+
"""
|
| 102 |
+
assert x.is_contiguous(), "Input tensor must be contiguous"
|
| 103 |
+
assert x.size(-1) % block_size == 0, (
|
| 104 |
+
f"Last dimension size must be divisible by block_size (block_size={block_size})"
|
| 105 |
+
)
|
| 106 |
+
N = x.size(-1)
|
| 107 |
+
y = torch.empty_like(x, dtype=torch.float8_e4m3fn)
|
| 108 |
+
s = x.new_empty(*x.size()[:-1], N // block_size, dtype=torch.float32)
|
| 109 |
+
kernel = act_quant_kernel(N, round_scale=scale_fmt is not None)
|
| 110 |
+
kernel(x.view(-1, N), y.view(-1, N), s.view(-1, N // block_size))
|
| 111 |
+
return y, s
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
@tilelang.jit(pass_configs=pass_configs)
|
| 115 |
+
def fp8_gemm_kernel(N, K, out_dtype=BF16, accum_dtype="float32"):
|
| 116 |
+
assert out_dtype in [BF16, "float32"]
|
| 117 |
+
|
| 118 |
+
M = T.symbolic("M")
|
| 119 |
+
group_size = 128
|
| 120 |
+
block_M = 32
|
| 121 |
+
block_N = 128
|
| 122 |
+
block_K = 128
|
| 123 |
+
|
| 124 |
+
@T.prim_func
|
| 125 |
+
def fp8_gemm_kernel_(
|
| 126 |
+
A: T.Tensor[(M, K), FP8],
|
| 127 |
+
B: T.Tensor[(N, K), FP8],
|
| 128 |
+
C: T.Tensor[(M, N), out_dtype],
|
| 129 |
+
scales_a: T.Tensor[(M, T.ceildiv(K, group_size)), FP32],
|
| 130 |
+
scales_b: T.Tensor[(T.ceildiv(N, group_size), T.ceildiv(K, group_size)), FP32],
|
| 131 |
+
):
|
| 132 |
+
with T.Kernel(T.ceildiv(N, block_N), T.ceildiv(M, block_M), threads=128) as (
|
| 133 |
+
bx,
|
| 134 |
+
by,
|
| 135 |
+
):
|
| 136 |
+
A_shared = T.alloc_shared((block_M, block_K), FP8)
|
| 137 |
+
B_shared = T.alloc_shared((block_N, block_K), FP8)
|
| 138 |
+
C_shared = T.alloc_shared((block_M, block_N), out_dtype)
|
| 139 |
+
Scale_C_shared = T.alloc_shared((block_M), FP32)
|
| 140 |
+
C_local = T.alloc_fragment((block_M, block_N), accum_dtype)
|
| 141 |
+
C_local_accum = T.alloc_fragment((block_M, block_N), accum_dtype)
|
| 142 |
+
|
| 143 |
+
# Improve L2 Cache
|
| 144 |
+
T.use_swizzle(panel_size=10)
|
| 145 |
+
|
| 146 |
+
T.clear(C_local)
|
| 147 |
+
T.clear(C_local_accum)
|
| 148 |
+
K_iters = T.ceildiv(K, block_K)
|
| 149 |
+
for k in T.Pipelined(K_iters, num_stages=4):
|
| 150 |
+
# Load A into shared memory
|
| 151 |
+
T.copy(A[by * block_M, k * block_K], A_shared)
|
| 152 |
+
# Load B into shared memory
|
| 153 |
+
T.copy(B[bx * block_N, k * block_K], B_shared)
|
| 154 |
+
# Load scale into shared memory
|
| 155 |
+
Scale_B = scales_b[bx * block_N // group_size, k]
|
| 156 |
+
for i in T.Parallel(block_M):
|
| 157 |
+
Scale_C_shared[i] = scales_a[by * block_M + i, k] * Scale_B
|
| 158 |
+
|
| 159 |
+
T.gemm(A_shared, B_shared, C_local, transpose_B=True)
|
| 160 |
+
# Promote to enable 2xAcc
|
| 161 |
+
for i, j in T.Parallel(block_M, block_N):
|
| 162 |
+
C_local_accum[i, j] += C_local[i, j] * Scale_C_shared[i]
|
| 163 |
+
T.clear(C_local)
|
| 164 |
+
# TMA store
|
| 165 |
+
T.copy(C_local_accum, C_shared)
|
| 166 |
+
T.copy(C_shared, C[by * block_M, bx * block_N])
|
| 167 |
+
|
| 168 |
+
return fp8_gemm_kernel_
|
| 169 |
+
|
| 170 |
+
|
| 171 |
+
def fp8_gemm(
|
| 172 |
+
a: torch.Tensor, a_s: torch.Tensor, b: torch.Tensor, b_s: torch.Tensor
|
| 173 |
+
) -> torch.Tensor:
|
| 174 |
+
"""
|
| 175 |
+
Perform a matrix multiplication using FP8 precision.
|
| 176 |
+
|
| 177 |
+
Args:
|
| 178 |
+
a (torch.Tensor): The first input matrix, must be contiguous.
|
| 179 |
+
a_s (torch.Tensor): The scaling factor for the first input matrix, must be contiguous.
|
| 180 |
+
b (torch.Tensor): The second input matrix, must be contiguous.
|
| 181 |
+
b_s (torch.Tensor): The scaling factor for the second input matrix, must be contiguous.
|
| 182 |
+
|
| 183 |
+
Returns:
|
| 184 |
+
torch.Tensor: The result of the matrix multiplication.
|
| 185 |
+
"""
|
| 186 |
+
assert a.is_contiguous() and b.is_contiguous(), "Input tensors must be contiguous"
|
| 187 |
+
assert a_s.is_contiguous() and b_s.is_contiguous(), (
|
| 188 |
+
"Scaling factor tensors must be contiguous"
|
| 189 |
+
)
|
| 190 |
+
K = a.size(-1)
|
| 191 |
+
M = a.numel() // K
|
| 192 |
+
N = b.size(0)
|
| 193 |
+
c = a.new_empty(*a.size()[:-1], N, dtype=torch.get_default_dtype())
|
| 194 |
+
kernel = fp8_gemm_kernel(N, K)
|
| 195 |
+
kernel(a.view(M, K), b, c.view(M, N), a_s.view(M, -1), b_s)
|
| 196 |
+
return c
|
| 197 |
+
|
| 198 |
+
|
| 199 |
+
@tilelang.jit(out_idx=[4], pass_configs=pass_configs)
|
| 200 |
+
def fp8_index_kernel(h: int, d: int):
|
| 201 |
+
b = T.symbolic("b")
|
| 202 |
+
m = T.symbolic("m")
|
| 203 |
+
n = T.symbolic("n")
|
| 204 |
+
|
| 205 |
+
blk_n1 = 512
|
| 206 |
+
blk_n2 = 128
|
| 207 |
+
|
| 208 |
+
@T.prim_func
|
| 209 |
+
def fp8_index_kernel_(
|
| 210 |
+
q: T.Tensor[(b, m, h, d), FP8],
|
| 211 |
+
q_s: T.Tensor[(b, m, h), FP32],
|
| 212 |
+
k: T.Tensor[(b, n, d), FP8],
|
| 213 |
+
k_s: T.Tensor[(b, n), FP32],
|
| 214 |
+
o: T.Tensor[(b, m, n), FP32],
|
| 215 |
+
) -> None:
|
| 216 |
+
with T.Kernel(b, m, T.ceildiv(n, blk_n1)) as (i_b, i_m, i1_n):
|
| 217 |
+
q_smem = T.alloc_shared((h, d), FP8)
|
| 218 |
+
T.copy(q[i_b, i_m, 0, 0], q_smem)
|
| 219 |
+
|
| 220 |
+
q_s_frag = T.alloc_fragment(h, FP32)
|
| 221 |
+
T.copy(q_s[i_b, i_m, 0], q_s_frag)
|
| 222 |
+
|
| 223 |
+
for i2_n in T.Pipelined(blk_n1 // blk_n2, num_stages=2):
|
| 224 |
+
k_smem = T.alloc_shared((blk_n2, d), FP8)
|
| 225 |
+
T.copy(k[i_b, i1_n * blk_n1 + i2_n * blk_n2, 0], k_smem)
|
| 226 |
+
|
| 227 |
+
k_s_frag = T.alloc_fragment(blk_n2, FP32)
|
| 228 |
+
T.copy(k_s[i_b, i1_n * blk_n1 + i2_n * blk_n2], k_s_frag)
|
| 229 |
+
|
| 230 |
+
logits = T.alloc_fragment((blk_n2, h), FP32)
|
| 231 |
+
T.gemm(
|
| 232 |
+
k_smem,
|
| 233 |
+
q_smem,
|
| 234 |
+
logits,
|
| 235 |
+
transpose_A=False,
|
| 236 |
+
transpose_B=True,
|
| 237 |
+
clear_accum=True,
|
| 238 |
+
)
|
| 239 |
+
|
| 240 |
+
for i_h, i3_n in T.Parallel(h, blk_n2):
|
| 241 |
+
logits[i3_n, i_h] = T.max(logits[i3_n, i_h], 0) * q_s_frag[i_h]
|
| 242 |
+
|
| 243 |
+
logits_sum = T.alloc_fragment(blk_n2, FP32)
|
| 244 |
+
T.reduce_sum(logits, logits_sum, dim=1)
|
| 245 |
+
|
| 246 |
+
for i3_n in T.Parallel(blk_n2):
|
| 247 |
+
logits_sum[i3_n] *= k_s_frag[i3_n]
|
| 248 |
+
|
| 249 |
+
T.copy(logits_sum, o[i_b, i_m, i1_n * blk_n1 + i2_n * blk_n2])
|
| 250 |
+
|
| 251 |
+
return fp8_index_kernel_
|
| 252 |
+
|
| 253 |
+
|
| 254 |
+
def fp8_index(
|
| 255 |
+
q: torch.Tensor,
|
| 256 |
+
q_s: torch.Tensor,
|
| 257 |
+
k: torch.Tensor,
|
| 258 |
+
k_s: torch.Tensor,
|
| 259 |
+
) -> torch.Tensor:
|
| 260 |
+
"""
|
| 261 |
+
Perform index score using FP8 precision.
|
| 262 |
+
|
| 263 |
+
Args:
|
| 264 |
+
q (torch.Tensor): The Q tensor, must be contiguous.
|
| 265 |
+
q_s (torch.Tensor): The scaling factor for Q (float), must be contiguous.
|
| 266 |
+
k (torch.Tensor): The K tensor, must be contiguous.
|
| 267 |
+
k_s (torch.Tensor): The scaling factor for K (e8m0 here), must be contiguous.
|
| 268 |
+
|
| 269 |
+
fp8 q @ fp8 k -> fp32 logits
|
| 270 |
+
relu(fp32 logits) * q_s (weights) -> fp32 logits
|
| 271 |
+
fp32 logits -> fp32 logits_sum
|
| 272 |
+
fp32 logits_sum * k_s (e8m0) -> fp32 index_score
|
| 273 |
+
"""
|
| 274 |
+
return fp8_index_kernel(q.shape[2], q.shape[3])(q, q_s, k, k_s)
|
inference/model.py
ADDED
|
@@ -0,0 +1,923 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
from dataclasses import dataclass
|
| 3 |
+
from typing import Tuple, Optional, Literal
|
| 4 |
+
|
| 5 |
+
import torch
|
| 6 |
+
from torch import nn
|
| 7 |
+
import torch.nn.functional as F
|
| 8 |
+
import torch.distributed as dist
|
| 9 |
+
|
| 10 |
+
from kernel import act_quant, fp8_gemm, fp8_index
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
world_size = 1
|
| 14 |
+
rank = 0
|
| 15 |
+
block_size = 128
|
| 16 |
+
|
| 17 |
+
@dataclass
|
| 18 |
+
class ModelArgs:
|
| 19 |
+
"""
|
| 20 |
+
Data class for defining model arguments and hyperparameters.
|
| 21 |
+
|
| 22 |
+
Attributes:
|
| 23 |
+
max_batch_size (int): Maximum batch size.
|
| 24 |
+
max_seq_len (int): Maximum sequence length.
|
| 25 |
+
dtype (Literal["bf16", "fp8"]): Data type for computations.
|
| 26 |
+
scale_fmt (Optional[str]): Format for quantization scale.
|
| 27 |
+
vocab_size (int): Vocabulary size.
|
| 28 |
+
dim (int): Model dimension.
|
| 29 |
+
inter_dim (int): Intermediate dimension for MLP layers.
|
| 30 |
+
moe_inter_dim (int): Intermediate dimension for MoE layers.
|
| 31 |
+
n_layers (int): Number of transformer layers.
|
| 32 |
+
n_dense_layers (int): Number of dense layers in the model.
|
| 33 |
+
n_heads (int): Number of attention heads.
|
| 34 |
+
n_routed_experts (int): Number of routed experts for MoE layers.
|
| 35 |
+
n_shared_experts (int): Number of shared experts for MoE layers.
|
| 36 |
+
n_activated_experts (int): Number of activated experts in MoE layers.
|
| 37 |
+
n_expert_groups (int): Number of expert groups.
|
| 38 |
+
n_limited_groups (int): Number of limited groups for MoE routing.
|
| 39 |
+
score_func (Literal["softmax", "sigmoid"]): Scoring function for MoE routing.
|
| 40 |
+
route_scale (float): Scaling factor for routing scores.
|
| 41 |
+
q_lora_rank (int): LoRA rank for query projections.
|
| 42 |
+
kv_lora_rank (int): LoRA rank for key-value projections.
|
| 43 |
+
qk_nope_head_dim (int): Dimension for query-key projections without positional embeddings.
|
| 44 |
+
qk_rope_head_dim (int): Dimension for query-key projections with rotary embeddings.
|
| 45 |
+
v_head_dim (int): Dimension for value projections.
|
| 46 |
+
original_seq_len (int): Original sequence length.
|
| 47 |
+
rope_theta (float): Base for rotary positional encoding.
|
| 48 |
+
rope_factor (float): Scaling factor for extended sequence lengths.
|
| 49 |
+
beta_fast (int): Fast beta correction factor.
|
| 50 |
+
beta_slow (int): Slow beta correction factor.
|
| 51 |
+
mscale (float): Scaling factor for extended attention.
|
| 52 |
+
index_head_dim (int): Dimension for index head.
|
| 53 |
+
index_topk (int): Top-k for index head.
|
| 54 |
+
"""
|
| 55 |
+
max_batch_size: int = 8
|
| 56 |
+
max_seq_len: int = 4096 * 4
|
| 57 |
+
dtype: Literal["bf16", "fp8"] = "bf16"
|
| 58 |
+
scale_fmt: Optional[str] = None
|
| 59 |
+
vocab_size: int = 102400
|
| 60 |
+
dim: int = 2048
|
| 61 |
+
inter_dim: int = 10944
|
| 62 |
+
moe_inter_dim: int = 1408
|
| 63 |
+
n_layers: int = 27
|
| 64 |
+
n_dense_layers: int = 1
|
| 65 |
+
n_heads: int = 16
|
| 66 |
+
# moe
|
| 67 |
+
n_routed_experts: int = 64
|
| 68 |
+
n_shared_experts: int = 2
|
| 69 |
+
n_activated_experts: int = 6
|
| 70 |
+
n_expert_groups: int = 1
|
| 71 |
+
n_limited_groups: int = 1
|
| 72 |
+
score_func: Literal["softmax", "sigmoid"] = "softmax"
|
| 73 |
+
route_scale: float = 1.
|
| 74 |
+
# mla
|
| 75 |
+
q_lora_rank: int = 0
|
| 76 |
+
kv_lora_rank: int = 512
|
| 77 |
+
qk_nope_head_dim: int = 128
|
| 78 |
+
qk_rope_head_dim: int = 64
|
| 79 |
+
v_head_dim: int = 128
|
| 80 |
+
# yarn
|
| 81 |
+
original_seq_len: int = 4096
|
| 82 |
+
rope_theta: float = 10000.0
|
| 83 |
+
rope_factor: float = 40
|
| 84 |
+
beta_fast: int = 32
|
| 85 |
+
beta_slow: int = 1
|
| 86 |
+
mscale: float = 1.
|
| 87 |
+
# index
|
| 88 |
+
index_n_heads: int = 64
|
| 89 |
+
index_head_dim: int = 128
|
| 90 |
+
index_topk: int = 2048
|
| 91 |
+
|
| 92 |
+
class ParallelEmbedding(nn.Module):
|
| 93 |
+
"""
|
| 94 |
+
Embedding layer with parallelism support across distributed processes.
|
| 95 |
+
|
| 96 |
+
Args:
|
| 97 |
+
vocab_size (int): Vocabulary size.
|
| 98 |
+
dim (int): Embedding dimension.
|
| 99 |
+
"""
|
| 100 |
+
def __init__(self, vocab_size: int, dim: int):
|
| 101 |
+
super().__init__()
|
| 102 |
+
self.vocab_size = vocab_size
|
| 103 |
+
self.dim = dim
|
| 104 |
+
assert vocab_size % world_size == 0, f"Vocabulary size must be divisible by world size (world_size={world_size})"
|
| 105 |
+
self.part_vocab_size = (vocab_size // world_size)
|
| 106 |
+
self.vocab_start_idx = rank * self.part_vocab_size
|
| 107 |
+
self.vocab_end_idx = self.vocab_start_idx + self.part_vocab_size
|
| 108 |
+
self.weight = nn.Parameter(torch.empty(self.part_vocab_size, self.dim))
|
| 109 |
+
|
| 110 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 111 |
+
"""
|
| 112 |
+
Forward pass for parallel embedding layer.
|
| 113 |
+
|
| 114 |
+
Args:
|
| 115 |
+
x (torch.Tensor): Input tensor containing token indices.
|
| 116 |
+
|
| 117 |
+
Returns:
|
| 118 |
+
torch.Tensor: Embedded representations.
|
| 119 |
+
|
| 120 |
+
Raises:
|
| 121 |
+
ValueError: If `world_size` is not defined.
|
| 122 |
+
"""
|
| 123 |
+
if world_size > 1:
|
| 124 |
+
mask = (x < self.vocab_start_idx) | (x >= self.vocab_end_idx)
|
| 125 |
+
x = x - self.vocab_start_idx
|
| 126 |
+
x[mask] = 0
|
| 127 |
+
y = F.embedding(x, self.weight)
|
| 128 |
+
if world_size > 1:
|
| 129 |
+
y[mask] = 0
|
| 130 |
+
dist.all_reduce(y)
|
| 131 |
+
return y
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def linear(x: torch.Tensor, weight: torch.Tensor, bias: Optional[torch.Tensor] = None,
|
| 135 |
+
scale_fmt: Optional[str] = None) -> torch.Tensor:
|
| 136 |
+
"""
|
| 137 |
+
Applies a linear transformation to the incoming data: y = xA^T + b.
|
| 138 |
+
This function supports specialized implementations based on quantization
|
| 139 |
+
and tensor formats.
|
| 140 |
+
|
| 141 |
+
Args:
|
| 142 |
+
x (torch.Tensor): The input tensor.
|
| 143 |
+
weight (torch.Tensor): The weight tensor. It may be quantized and
|
| 144 |
+
requires dequantization for certain cases.
|
| 145 |
+
bias (Optional[torch.Tensor]): The bias tensor to be added. Default is None.
|
| 146 |
+
scale_fmt (Optional[str]): The format of scaling factors.
|
| 147 |
+
|
| 148 |
+
Returns:
|
| 149 |
+
torch.Tensor: The result of the linear transformation, which may involve
|
| 150 |
+
quantization-aware computations depending on the input parameters.
|
| 151 |
+
|
| 152 |
+
Notes:
|
| 153 |
+
- If `weight` is quantized (e.g., `element_size() == 1`), a dequantized version
|
| 154 |
+
is used for computation.
|
| 155 |
+
- For other cases, the function applies quantization to `x` and uses `fp8_gemm` for computation.
|
| 156 |
+
"""
|
| 157 |
+
assert bias is None
|
| 158 |
+
|
| 159 |
+
if weight.dtype != torch.float8_e4m3fn:
|
| 160 |
+
return F.linear(x, weight)
|
| 161 |
+
else:
|
| 162 |
+
x, scale = act_quant(x, block_size, scale_fmt)
|
| 163 |
+
return fp8_gemm(x, scale, weight, weight.scale)
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
class Linear(nn.Module):
|
| 167 |
+
"""
|
| 168 |
+
Custom linear layer with support for quantized weights and optional bias.
|
| 169 |
+
|
| 170 |
+
Args:
|
| 171 |
+
in_features (int): Number of input features.
|
| 172 |
+
out_features (int): Number of output features.
|
| 173 |
+
bias (bool): Whether to include a bias term. Defaults to False.
|
| 174 |
+
dtype (optional): Data type for the layer. Defaults to `torch.bfloat16`.
|
| 175 |
+
"""
|
| 176 |
+
dtype = torch.bfloat16
|
| 177 |
+
scale_fmt: Optional[str] = None
|
| 178 |
+
|
| 179 |
+
def __init__(self, in_features: int, out_features: int, bias: bool = False, dtype = None):
|
| 180 |
+
super().__init__()
|
| 181 |
+
self.in_features = in_features
|
| 182 |
+
self.out_features = out_features
|
| 183 |
+
self.weight = nn.Parameter(torch.empty(out_features, in_features, dtype=dtype or Linear.dtype))
|
| 184 |
+
if self.weight.element_size() == 1:
|
| 185 |
+
scale_out_features = (out_features + block_size - 1) // block_size
|
| 186 |
+
scale_in_features = (in_features + block_size - 1) // block_size
|
| 187 |
+
self.weight.scale = self.scale = nn.Parameter(torch.empty(scale_out_features, scale_in_features, dtype=torch.float32))
|
| 188 |
+
else:
|
| 189 |
+
self.register_parameter("scale", None)
|
| 190 |
+
if bias:
|
| 191 |
+
self.bias = nn.Parameter(torch.empty(out_features))
|
| 192 |
+
else:
|
| 193 |
+
self.register_parameter("bias", None)
|
| 194 |
+
|
| 195 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 196 |
+
"""
|
| 197 |
+
Forward pass for the custom linear layer.
|
| 198 |
+
|
| 199 |
+
Args:
|
| 200 |
+
x (torch.Tensor): Input tensor.
|
| 201 |
+
|
| 202 |
+
Returns:
|
| 203 |
+
torch.Tensor: Transformed tensor after linear computation.
|
| 204 |
+
"""
|
| 205 |
+
return linear(x, self.weight, self.bias, self.scale_fmt)
|
| 206 |
+
|
| 207 |
+
|
| 208 |
+
class ColumnParallelLinear(Linear):
|
| 209 |
+
"""
|
| 210 |
+
Linear layer with column parallelism, splitting output features across distributed processes.
|
| 211 |
+
|
| 212 |
+
Args:
|
| 213 |
+
in_features (int): Number of input features.
|
| 214 |
+
out_features (int): Total number of output features.
|
| 215 |
+
bias (bool): Whether to include a bias term. Defaults to False.
|
| 216 |
+
dtype (optional): Data type for the layer. Defaults to `torch.bfloat16`.
|
| 217 |
+
"""
|
| 218 |
+
def __init__(self, in_features: int, out_features: int, bias: bool = False, dtype = None):
|
| 219 |
+
assert out_features % world_size == 0, f"Output features must be divisible by world size (world_size={world_size})"
|
| 220 |
+
self.part_out_features = out_features // world_size
|
| 221 |
+
super().__init__(in_features, self.part_out_features, bias, dtype)
|
| 222 |
+
|
| 223 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 224 |
+
"""
|
| 225 |
+
Forward pass for column parallel linear layer.
|
| 226 |
+
|
| 227 |
+
Args:
|
| 228 |
+
x (torch.Tensor): Input tensor.
|
| 229 |
+
|
| 230 |
+
Returns:
|
| 231 |
+
torch.Tensor: Transformed tensor with column-parallel computation.
|
| 232 |
+
"""
|
| 233 |
+
y = linear(x, self.weight, self.bias, self.scale_fmt)
|
| 234 |
+
return y
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
class RowParallelLinear(Linear):
|
| 238 |
+
"""
|
| 239 |
+
Linear layer with row parallelism, splitting input features across distributed processes.
|
| 240 |
+
|
| 241 |
+
Args:
|
| 242 |
+
in_features (int): Total number of input features.
|
| 243 |
+
out_features (int): Number of output features.
|
| 244 |
+
bias (bool): Whether to include a bias term. Defaults to False.
|
| 245 |
+
dtype (optional): Data type for the layer. Defaults to `torch.bfloat16`.
|
| 246 |
+
"""
|
| 247 |
+
def __init__(self, in_features: int, out_features: int, bias: bool = False, reduce_output = True, dtype = None):
|
| 248 |
+
assert in_features % world_size == 0, f"Input features must be divisible by world size (world_size={world_size})"
|
| 249 |
+
self.part_in_features = in_features // world_size
|
| 250 |
+
self.reduce_output = reduce_output
|
| 251 |
+
super().__init__(self.part_in_features, out_features, bias, dtype)
|
| 252 |
+
|
| 253 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 254 |
+
"""
|
| 255 |
+
Forward pass for row parallel linear layer.
|
| 256 |
+
|
| 257 |
+
Args:
|
| 258 |
+
x (torch.Tensor): Input tensor.
|
| 259 |
+
|
| 260 |
+
Returns:
|
| 261 |
+
torch.Tensor: Transformed tensor with row-parallel computation.
|
| 262 |
+
"""
|
| 263 |
+
y = linear(x, self.weight, None, self.scale_fmt)
|
| 264 |
+
if self.reduce_output and world_size > 1:
|
| 265 |
+
y = y.float()
|
| 266 |
+
dist.all_reduce(y)
|
| 267 |
+
if self.bias is not None:
|
| 268 |
+
y += self.bias
|
| 269 |
+
return y.type_as(x)
|
| 270 |
+
|
| 271 |
+
|
| 272 |
+
class RMSNorm(nn.Module):
|
| 273 |
+
"""
|
| 274 |
+
Root Mean Square Layer Normalization (RMSNorm).
|
| 275 |
+
|
| 276 |
+
Args:
|
| 277 |
+
dim (int): Dimension of the input tensor.
|
| 278 |
+
eps (float): Epsilon value for numerical stability. Defaults to 1e-6.
|
| 279 |
+
"""
|
| 280 |
+
def __init__(self, dim: int, eps: float = 1e-6):
|
| 281 |
+
super().__init__()
|
| 282 |
+
self.dim = dim
|
| 283 |
+
self.eps = eps
|
| 284 |
+
self.weight = nn.Parameter(torch.ones(dim, dtype=torch.float32))
|
| 285 |
+
|
| 286 |
+
def forward(self, x: torch.Tensor, residual: Optional[torch.Tensor] = None):
|
| 287 |
+
"""
|
| 288 |
+
Forward pass for RMSNorm.
|
| 289 |
+
|
| 290 |
+
Args:
|
| 291 |
+
x (torch.Tensor): Input tensor.
|
| 292 |
+
|
| 293 |
+
Returns:
|
| 294 |
+
torch.Tensor: Normalized tensor with the same shape as input.
|
| 295 |
+
"""
|
| 296 |
+
dtype = x.dtype
|
| 297 |
+
if residual is None:
|
| 298 |
+
x = x.float()
|
| 299 |
+
var = x.pow(2).mean(-1, keepdim=True)
|
| 300 |
+
x = x * torch.rsqrt(var + self.eps)
|
| 301 |
+
return (self.weight * x).to(dtype)
|
| 302 |
+
else:
|
| 303 |
+
x = residual = x.float() + residual.float()
|
| 304 |
+
var = x.pow(2).mean(-1, keepdim=True)
|
| 305 |
+
x = x * torch.rsqrt(var + self.eps)
|
| 306 |
+
return (self.weight * x).to(dtype), residual.to(dtype)
|
| 307 |
+
|
| 308 |
+
|
| 309 |
+
class LayerNorm(nn.Module):
|
| 310 |
+
"""
|
| 311 |
+
Layer Normalization.
|
| 312 |
+
"""
|
| 313 |
+
def __init__(self, dim: int, eps: float = 1e-6):
|
| 314 |
+
super().__init__()
|
| 315 |
+
self.dim = dim
|
| 316 |
+
self.eps = eps
|
| 317 |
+
self.weight = nn.Parameter(torch.ones(dim, dtype=torch.float32))
|
| 318 |
+
self.bias = nn.Parameter(torch.zeros(dim, dtype=torch.float32))
|
| 319 |
+
|
| 320 |
+
def forward(self, x: torch.Tensor):
|
| 321 |
+
return F.layer_norm(x.float(), (self.dim,), self.weight, self.bias, self.eps).type_as(x)
|
| 322 |
+
|
| 323 |
+
|
| 324 |
+
def precompute_freqs_cis(args: ModelArgs) -> torch.Tensor:
|
| 325 |
+
"""
|
| 326 |
+
Precomputes frequency-based complex exponential values for rotary positional embeddings.
|
| 327 |
+
|
| 328 |
+
Args:
|
| 329 |
+
args (ModelArgs): Model arguments containing positional embedding parameters.
|
| 330 |
+
|
| 331 |
+
Returns:
|
| 332 |
+
torch.Tensor: Precomputed complex exponential values for positional embeddings.
|
| 333 |
+
"""
|
| 334 |
+
dim = args.qk_rope_head_dim
|
| 335 |
+
seqlen = args.max_seq_len
|
| 336 |
+
beta_fast = args.beta_fast
|
| 337 |
+
beta_slow = args.beta_slow
|
| 338 |
+
base = args.rope_theta
|
| 339 |
+
factor = args.rope_factor
|
| 340 |
+
|
| 341 |
+
def find_correction_dim(num_rotations, dim, base, max_seq_len):
|
| 342 |
+
"""
|
| 343 |
+
Computes the correction dimension for a given number of rotations in the rotary positional embedding.
|
| 344 |
+
|
| 345 |
+
Args:
|
| 346 |
+
num_rotations (float): Number of rotations to compute the correction for.
|
| 347 |
+
dim (int): Dimensionality of the embedding space.
|
| 348 |
+
base (float): Base value for the exponential computation.
|
| 349 |
+
max_seq_len (int): Maximum sequence length.
|
| 350 |
+
|
| 351 |
+
Returns:
|
| 352 |
+
float: The correction dimension based on the input parameters.
|
| 353 |
+
"""
|
| 354 |
+
return dim * math.log(max_seq_len / (num_rotations * 2 * math.pi)) / (2 * math.log(base))
|
| 355 |
+
|
| 356 |
+
def find_correction_range(low_rot, high_rot, dim, base, max_seq_len):
|
| 357 |
+
"""
|
| 358 |
+
Computes the range of correction dimensions for rotary positional embeddings.
|
| 359 |
+
|
| 360 |
+
Args:
|
| 361 |
+
low_rot (float): Lower bound for the number of rotations.
|
| 362 |
+
high_rot (float): Upper bound for the number of rotations.
|
| 363 |
+
dim (int): Dimensionality of the embedding space.
|
| 364 |
+
base (float): Base value for the exponential computation.
|
| 365 |
+
max_seq_len (int): Maximum sequence length.
|
| 366 |
+
|
| 367 |
+
Returns:
|
| 368 |
+
Tuple[int, int]: The range of correction dimensions (low, high), clamped to valid indices.
|
| 369 |
+
"""
|
| 370 |
+
low = math.floor(find_correction_dim(low_rot, dim, base, max_seq_len))
|
| 371 |
+
high = math.ceil(find_correction_dim(high_rot, dim, base, max_seq_len))
|
| 372 |
+
return max(low, 0), min(high, dim-1)
|
| 373 |
+
|
| 374 |
+
def linear_ramp_factor(min, max, dim):
|
| 375 |
+
"""
|
| 376 |
+
Computes a linear ramp function used to smooth values between a minimum and maximum range.
|
| 377 |
+
|
| 378 |
+
Args:
|
| 379 |
+
min (float): Minimum value for the ramp function.
|
| 380 |
+
max (float): Maximum value for the ramp function.
|
| 381 |
+
dim (int): Dimensionality of the ramp tensor.
|
| 382 |
+
|
| 383 |
+
Returns:
|
| 384 |
+
torch.Tensor: A tensor of shape (dim,) with values linearly interpolated between 0 and 1,
|
| 385 |
+
clamped to the range [0, 1].
|
| 386 |
+
"""
|
| 387 |
+
if min == max:
|
| 388 |
+
max += 0.001
|
| 389 |
+
linear_func = (torch.arange(dim, dtype=torch.float32) - min) / (max - min)
|
| 390 |
+
ramp_func = torch.clamp(linear_func, 0, 1)
|
| 391 |
+
return ramp_func
|
| 392 |
+
|
| 393 |
+
freqs = 1.0 / (base ** (torch.arange(0, dim, 2, dtype=torch.float32) / dim))
|
| 394 |
+
if seqlen > args.original_seq_len:
|
| 395 |
+
low, high = find_correction_range(beta_fast, beta_slow, dim, base, args.original_seq_len)
|
| 396 |
+
smooth = 1 - linear_ramp_factor(low, high, dim // 2)
|
| 397 |
+
freqs = freqs / factor * (1 - smooth) + freqs * smooth
|
| 398 |
+
|
| 399 |
+
t = torch.arange(seqlen)
|
| 400 |
+
freqs = torch.outer(t, freqs)
|
| 401 |
+
freqs_cis = torch.polar(torch.ones_like(freqs), freqs)
|
| 402 |
+
return freqs_cis
|
| 403 |
+
|
| 404 |
+
|
| 405 |
+
def apply_rotary_emb(x: torch.Tensor, freqs_cis: torch.Tensor, interleaved: bool = True) -> torch.Tensor:
|
| 406 |
+
"""
|
| 407 |
+
Applies rotary positional embeddings to the input tensor.
|
| 408 |
+
|
| 409 |
+
Args:
|
| 410 |
+
x (torch.Tensor): Input tensor with positional embeddings to be applied.
|
| 411 |
+
freqs_cis (torch.Tensor): Precomputed complex exponential values for positional embeddings.
|
| 412 |
+
|
| 413 |
+
Returns:
|
| 414 |
+
torch.Tensor: Tensor with rotary embeddings applied.
|
| 415 |
+
"""
|
| 416 |
+
dtype = x.dtype
|
| 417 |
+
shape = x.shape
|
| 418 |
+
if not interleaved:
|
| 419 |
+
x = x.view(*shape[:-1], 2, -1).transpose(-1, -2).contiguous()
|
| 420 |
+
x = torch.view_as_complex(x.float().view(*shape[:-1], -1, 2))
|
| 421 |
+
freqs_cis = freqs_cis.view(1, x.size(1), 1, x.size(-1))
|
| 422 |
+
y = torch.view_as_real(x * freqs_cis).flatten(3)
|
| 423 |
+
if not interleaved:
|
| 424 |
+
y = torch.cat([y[..., 0::2], y[..., 1::2]], dim=-1)
|
| 425 |
+
return y.to(dtype)
|
| 426 |
+
|
| 427 |
+
|
| 428 |
+
def rotate_activation(x: torch.Tensor) -> torch.Tensor:
|
| 429 |
+
assert x.dtype == torch.bfloat16
|
| 430 |
+
from fast_hadamard_transform import hadamard_transform
|
| 431 |
+
hidden_size = x.size(-1)
|
| 432 |
+
return hadamard_transform(x, scale=hidden_size ** -0.5)
|
| 433 |
+
|
| 434 |
+
|
| 435 |
+
class Indexer(torch.nn.Module):
|
| 436 |
+
def __init__(self, args: ModelArgs):
|
| 437 |
+
super().__init__()
|
| 438 |
+
self.dim: int = args.dim
|
| 439 |
+
self.n_heads: int = args.index_n_heads
|
| 440 |
+
self.n_local_heads = args.index_n_heads // world_size
|
| 441 |
+
self.head_dim: int = args.index_head_dim
|
| 442 |
+
self.rope_head_dim: int = args.qk_rope_head_dim
|
| 443 |
+
self.index_topk: int = args.index_topk
|
| 444 |
+
self.q_lora_rank: int = args.q_lora_rank
|
| 445 |
+
self.wq_b = Linear(self.q_lora_rank, self.n_heads * self.head_dim)
|
| 446 |
+
self.wk = Linear(self.dim, self.head_dim)
|
| 447 |
+
self.k_norm = LayerNorm(self.head_dim)
|
| 448 |
+
# weights_proj in the checkpoint is stored in bf16, while the parameters here are stored in fp32 for convenient.
|
| 449 |
+
self.weights_proj = Linear(self.dim, self.n_heads, dtype=torch.float32)
|
| 450 |
+
self.softmax_scale = self.head_dim ** -0.5
|
| 451 |
+
self.scale_fmt = args.scale_fmt
|
| 452 |
+
|
| 453 |
+
self.register_buffer("k_cache", torch.zeros(args.max_batch_size, args.max_seq_len, self.head_dim, dtype=torch.float8_e4m3fn), persistent=False)
|
| 454 |
+
self.register_buffer("k_scale_cache", torch.zeros(args.max_batch_size, args.max_seq_len, self.head_dim // block_size, dtype=torch.float32), persistent=False)
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
def forward(self, x: torch.Tensor, qr: torch.Tensor, start_pos: int, freqs_cis: torch.Tensor, mask: Optional[torch.Tensor]):
|
| 458 |
+
bsz, seqlen, _ = x.size()
|
| 459 |
+
end_pos = start_pos + seqlen
|
| 460 |
+
q = self.wq_b(qr)
|
| 461 |
+
q = q.view(bsz, seqlen, self.n_heads, self.head_dim)
|
| 462 |
+
q_pe, q_nope = torch.split(q, [self.rope_head_dim, self.head_dim - self.rope_head_dim], dim=-1)
|
| 463 |
+
# rope in indexer is not interleaved
|
| 464 |
+
q_pe = apply_rotary_emb(q_pe, freqs_cis, False)
|
| 465 |
+
q = torch.cat([q_pe, q_nope], dim=-1)
|
| 466 |
+
k = self.wk(x)
|
| 467 |
+
k = self.k_norm(k)
|
| 468 |
+
k_pe, k_nope = torch.split(k, [self.rope_head_dim, self.head_dim - self.rope_head_dim], dim=-1)
|
| 469 |
+
# rope in indexer is not interleaved
|
| 470 |
+
k_pe = apply_rotary_emb(k_pe.unsqueeze(2), freqs_cis, False).squeeze(2)
|
| 471 |
+
k = torch.cat([k_pe, k_nope], dim=-1)
|
| 472 |
+
q = rotate_activation(q)
|
| 473 |
+
k = rotate_activation(k)
|
| 474 |
+
q_fp8, q_scale = act_quant(q, block_size, self.scale_fmt)
|
| 475 |
+
k_fp8, k_scale = act_quant(k, block_size, self.scale_fmt)
|
| 476 |
+
self.k_cache[:bsz, start_pos:end_pos] = k_fp8
|
| 477 |
+
self.k_scale_cache[:bsz, start_pos:end_pos] = k_scale
|
| 478 |
+
weights = self.weights_proj(x.float()) * self.n_heads ** -0.5
|
| 479 |
+
weights = weights.unsqueeze(-1) * q_scale * self.softmax_scale
|
| 480 |
+
index_score = fp8_index(q_fp8.contiguous(), weights, self.k_cache[:bsz, :end_pos].contiguous(), self.k_scale_cache[:bsz, :end_pos].contiguous())
|
| 481 |
+
if mask is not None:
|
| 482 |
+
index_score += mask
|
| 483 |
+
topk_indices = index_score.topk(min(self.index_topk, end_pos), dim=-1)[1]
|
| 484 |
+
topk_indices_ = topk_indices.clone()
|
| 485 |
+
dist.broadcast(topk_indices_, src=0)
|
| 486 |
+
assert torch.all(topk_indices == topk_indices_), f"{topk_indices=} {topk_indices_=}"
|
| 487 |
+
return topk_indices
|
| 488 |
+
|
| 489 |
+
|
| 490 |
+
def weight_dequant(weight, scale):
|
| 491 |
+
shape = weight.shape
|
| 492 |
+
assert weight.dim() == 2
|
| 493 |
+
weight = weight.view(shape[0] // block_size, block_size, shape[1] // block_size, block_size).transpose(1, 2).contiguous().view(-1, block_size * block_size)
|
| 494 |
+
weight = (weight.float() * scale.view(-1, 1).float()).to(torch.get_default_dtype()).view(shape[0] // block_size, shape[1] // block_size, block_size, block_size).transpose(1, 2).contiguous().view(shape)
|
| 495 |
+
return weight
|
| 496 |
+
|
| 497 |
+
|
| 498 |
+
class MLA(nn.Module):
|
| 499 |
+
"""
|
| 500 |
+
Multi-Head Latent Attention (MLA) Layer.
|
| 501 |
+
|
| 502 |
+
Attributes:
|
| 503 |
+
dim (int): Dimensionality of the input features.
|
| 504 |
+
n_heads (int): Number of attention heads.
|
| 505 |
+
n_local_heads (int): Number of local attention heads for distributed systems.
|
| 506 |
+
q_lora_rank (int): Rank for low-rank query projection.
|
| 507 |
+
kv_lora_rank (int): Rank for low-rank key/value projection.
|
| 508 |
+
qk_nope_head_dim (int): Dimensionality of non-positional query/key projections.
|
| 509 |
+
qk_rope_head_dim (int): Dimensionality of rotary-positional query/key projections.
|
| 510 |
+
qk_head_dim (int): Total dimensionality of query/key projections.
|
| 511 |
+
v_head_dim (int): Dimensionality of value projections.
|
| 512 |
+
softmax_scale (float): Scaling factor for softmax in attention computation.
|
| 513 |
+
"""
|
| 514 |
+
def __init__(self, args: ModelArgs):
|
| 515 |
+
super().__init__()
|
| 516 |
+
self.dim = args.dim
|
| 517 |
+
self.n_heads = args.n_heads
|
| 518 |
+
self.n_local_heads = args.n_heads // world_size
|
| 519 |
+
self.q_lora_rank = args.q_lora_rank
|
| 520 |
+
self.kv_lora_rank = args.kv_lora_rank
|
| 521 |
+
self.qk_nope_head_dim = args.qk_nope_head_dim
|
| 522 |
+
self.qk_rope_head_dim = args.qk_rope_head_dim
|
| 523 |
+
self.qk_head_dim = args.qk_nope_head_dim + args.qk_rope_head_dim
|
| 524 |
+
self.v_head_dim = args.v_head_dim
|
| 525 |
+
|
| 526 |
+
self.wq_a = Linear(self.dim, self.q_lora_rank)
|
| 527 |
+
self.q_norm = RMSNorm(self.q_lora_rank)
|
| 528 |
+
self.wq_b = ColumnParallelLinear(self.q_lora_rank, self.n_heads * self.qk_head_dim)
|
| 529 |
+
self.wkv_a = Linear(self.dim, self.kv_lora_rank + self.qk_rope_head_dim)
|
| 530 |
+
self.kv_norm = RMSNorm(self.kv_lora_rank)
|
| 531 |
+
self.wkv_b = ColumnParallelLinear(self.kv_lora_rank, self.n_heads * (self.qk_nope_head_dim + self.v_head_dim))
|
| 532 |
+
self.wo = RowParallelLinear(self.n_heads * self.v_head_dim, self.dim)
|
| 533 |
+
self.softmax_scale = self.qk_head_dim ** -0.5
|
| 534 |
+
self.scale_fmt = args.scale_fmt
|
| 535 |
+
if args.max_seq_len > args.original_seq_len:
|
| 536 |
+
mscale = 0.1 * args.mscale * math.log(args.rope_factor) + 1.0
|
| 537 |
+
self.softmax_scale = self.softmax_scale * mscale * mscale
|
| 538 |
+
|
| 539 |
+
self.indexer = Indexer(args)
|
| 540 |
+
|
| 541 |
+
self.register_buffer("kv_cache", torch.zeros(args.max_batch_size, args.max_seq_len, self.kv_lora_rank), persistent=False)
|
| 542 |
+
self.register_buffer("pe_cache", torch.zeros(args.max_batch_size, args.max_seq_len, self.qk_rope_head_dim), persistent=False)
|
| 543 |
+
self.dequant_wkv_b = None
|
| 544 |
+
|
| 545 |
+
def forward(self, x: torch.Tensor, start_pos: int, freqs_cis: torch.Tensor, mask: Optional[torch.Tensor]):
|
| 546 |
+
"""
|
| 547 |
+
Forward pass for the Multi-Head Latent Attention (MLA) Layer.
|
| 548 |
+
|
| 549 |
+
Args:
|
| 550 |
+
x (torch.Tensor): Input tensor of shape (batch_size, seq_len, dim).
|
| 551 |
+
start_pos (int): Starting position in the sequence for caching.
|
| 552 |
+
freqs_cis (torch.Tensor): Precomputed complex exponential values for rotary embeddings.
|
| 553 |
+
mask (Optional[torch.Tensor]): Mask tensor to exclude certain positions from attention.
|
| 554 |
+
|
| 555 |
+
Returns:
|
| 556 |
+
torch.Tensor: Output tensor with the same shape as the input.
|
| 557 |
+
"""
|
| 558 |
+
bsz, seqlen, _ = x.size()
|
| 559 |
+
end_pos = start_pos + seqlen
|
| 560 |
+
qr = self.q_norm(self.wq_a(x))
|
| 561 |
+
q = self.wq_b(qr)
|
| 562 |
+
q = q.view(bsz, seqlen, self.n_local_heads, self.qk_head_dim)
|
| 563 |
+
q_nope, q_pe = torch.split(q, [self.qk_nope_head_dim, self.qk_rope_head_dim], dim=-1)
|
| 564 |
+
q_pe = apply_rotary_emb(q_pe, freqs_cis)
|
| 565 |
+
kv = self.wkv_a(x)
|
| 566 |
+
kv, k_pe = torch.split(kv, [self.kv_lora_rank, self.qk_rope_head_dim], dim=-1)
|
| 567 |
+
kv = self.kv_norm(kv)
|
| 568 |
+
k_pe = apply_rotary_emb(k_pe.unsqueeze(2), freqs_cis)
|
| 569 |
+
# we use fp8 kv cache in actual deployment, so here we simulate the precision by casting kv to fp8 and then back to bf16.
|
| 570 |
+
kv_fp8, kv_scale = act_quant(kv, block_size, self.scale_fmt)
|
| 571 |
+
kv = (kv_fp8.view(-1, block_size).float() * kv_scale.view(-1, 1)).to(kv.dtype).view_as(kv)
|
| 572 |
+
self.kv_cache[:bsz, start_pos:end_pos] = kv
|
| 573 |
+
self.pe_cache[:bsz, start_pos:end_pos] = k_pe.squeeze(2)
|
| 574 |
+
if mask is not None: # MHA prefill
|
| 575 |
+
q = torch.cat([q_nope, q_pe], dim=-1)
|
| 576 |
+
kv = self.wkv_b(kv)
|
| 577 |
+
kv = kv.view(bsz, seqlen, self.n_local_heads, self.qk_nope_head_dim + self.v_head_dim)
|
| 578 |
+
k_nope, v = torch.split(kv, [self.qk_nope_head_dim, self.v_head_dim], dim=-1)
|
| 579 |
+
k = torch.cat([k_nope, k_pe.expand(-1, -1, self.n_local_heads, -1)], dim=-1)
|
| 580 |
+
scores = torch.einsum("bshd,bthd->bsht", q, k).mul_(self.softmax_scale)
|
| 581 |
+
|
| 582 |
+
# indexer
|
| 583 |
+
topk_indices = self.indexer(x, qr, start_pos, freqs_cis, mask)
|
| 584 |
+
index_mask = torch.full((bsz, seqlen, seqlen), float("-inf"), device=x.device).scatter_(-1, topk_indices, 0)
|
| 585 |
+
index_mask += mask
|
| 586 |
+
scores += index_mask.unsqueeze(2)
|
| 587 |
+
|
| 588 |
+
scores = scores.softmax(dim=-1)
|
| 589 |
+
x = torch.einsum("bsht,bthd->bshd", scores, v)
|
| 590 |
+
else: # MQA decode
|
| 591 |
+
if self.dequant_wkv_b is None and self.wkv_b.scale is not None:
|
| 592 |
+
self.dequant_wkv_b = weight_dequant(self.wkv_b.weight, self.wkv_b.scale)
|
| 593 |
+
wkv_b = self.wkv_b.weight if self.dequant_wkv_b is None else self.dequant_wkv_b
|
| 594 |
+
wkv_b = wkv_b.view(self.n_local_heads, -1, self.kv_lora_rank)
|
| 595 |
+
q_nope = torch.einsum("bshd,hdc->bshc", q_nope, wkv_b[:, :self.qk_nope_head_dim])
|
| 596 |
+
scores = (torch.einsum("bshc,btc->bsht", q_nope, self.kv_cache[:bsz, :end_pos]) +
|
| 597 |
+
torch.einsum("bshr,btr->bsht", q_pe, self.pe_cache[:bsz, :end_pos])) * self.softmax_scale
|
| 598 |
+
|
| 599 |
+
# indexer
|
| 600 |
+
topk_indices = self.indexer(x, qr, start_pos, freqs_cis, mask)
|
| 601 |
+
index_mask = torch.full((bsz, 1, end_pos), float("-inf"), device=x.device).scatter_(-1, topk_indices, 0)
|
| 602 |
+
scores += index_mask.unsqueeze(2)
|
| 603 |
+
|
| 604 |
+
scores = scores.softmax(dim=-1)
|
| 605 |
+
x = torch.einsum("bsht,btc->bshc", scores, self.kv_cache[:bsz, :end_pos])
|
| 606 |
+
x = torch.einsum("bshc,hdc->bshd", x, wkv_b[:, -self.v_head_dim:])
|
| 607 |
+
x = self.wo(x.flatten(2))
|
| 608 |
+
return x
|
| 609 |
+
|
| 610 |
+
|
| 611 |
+
class MLP(nn.Module):
|
| 612 |
+
"""
|
| 613 |
+
Multi-Layer Perceptron (MLP) used as a feed-forward layer.
|
| 614 |
+
|
| 615 |
+
Attributes:
|
| 616 |
+
w1 (nn.Module): Linear layer for input-to-hidden transformation.
|
| 617 |
+
w2 (nn.Module): Linear layer for hidden-to-output transformation.
|
| 618 |
+
w3 (nn.Module): Additional linear layer for feature transformation.
|
| 619 |
+
"""
|
| 620 |
+
def __init__(self, dim: int, inter_dim: int, reduce_output: bool = True):
|
| 621 |
+
"""
|
| 622 |
+
Initializes the MLP layer.
|
| 623 |
+
|
| 624 |
+
Args:
|
| 625 |
+
dim (int): Input and output dimensionality.
|
| 626 |
+
inter_dim (int): Hidden layer dimensionality.
|
| 627 |
+
"""
|
| 628 |
+
super().__init__()
|
| 629 |
+
self.w1 = ColumnParallelLinear(dim, inter_dim)
|
| 630 |
+
self.w2 = RowParallelLinear(inter_dim, dim, reduce_output=reduce_output)
|
| 631 |
+
self.w3 = ColumnParallelLinear(dim, inter_dim)
|
| 632 |
+
|
| 633 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 634 |
+
"""
|
| 635 |
+
Forward pass for the MLP layer.
|
| 636 |
+
|
| 637 |
+
Args:
|
| 638 |
+
x (torch.Tensor): Input tensor.
|
| 639 |
+
|
| 640 |
+
Returns:
|
| 641 |
+
torch.Tensor: Output tensor after MLP computation.
|
| 642 |
+
"""
|
| 643 |
+
return self.w2((F.silu(self.w1(x).float()) * self.w3(x).float()).type_as(x))
|
| 644 |
+
|
| 645 |
+
|
| 646 |
+
class Gate(nn.Module):
|
| 647 |
+
"""
|
| 648 |
+
Gating mechanism for routing inputs in a mixture-of-experts (MoE) model.
|
| 649 |
+
|
| 650 |
+
Attributes:
|
| 651 |
+
dim (int): Dimensionality of input features.
|
| 652 |
+
topk (int): Number of top experts activated for each input.
|
| 653 |
+
n_groups (int): Number of groups for routing.
|
| 654 |
+
topk_groups (int): Number of groups to route inputs to.
|
| 655 |
+
score_func (str): Scoring function ('softmax' or 'sigmoid').
|
| 656 |
+
route_scale (float): Scaling factor for routing weights.
|
| 657 |
+
weight (torch.nn.Parameter): Learnable weights for the gate.
|
| 658 |
+
bias (Optional[torch.nn.Parameter]): Optional bias term for the gate.
|
| 659 |
+
"""
|
| 660 |
+
def __init__(self, args: ModelArgs):
|
| 661 |
+
"""
|
| 662 |
+
Initializes the Gate module.
|
| 663 |
+
|
| 664 |
+
Args:
|
| 665 |
+
args (ModelArgs): Model arguments containing gating parameters.
|
| 666 |
+
"""
|
| 667 |
+
super().__init__()
|
| 668 |
+
self.dim = args.dim
|
| 669 |
+
self.topk = args.n_activated_experts
|
| 670 |
+
self.n_groups = args.n_expert_groups
|
| 671 |
+
self.topk_groups = args.n_limited_groups
|
| 672 |
+
self.score_func = args.score_func
|
| 673 |
+
self.route_scale = args.route_scale
|
| 674 |
+
self.weight = nn.Parameter(torch.empty(args.n_routed_experts, args.dim))
|
| 675 |
+
self.bias = nn.Parameter(torch.empty(args.n_routed_experts, dtype=torch.float32)) if self.dim == 7168 else None
|
| 676 |
+
|
| 677 |
+
def forward(self, x: torch.Tensor) -> Tuple[torch.Tensor, torch.Tensor]:
|
| 678 |
+
"""
|
| 679 |
+
Forward pass for the gating mechanism.
|
| 680 |
+
|
| 681 |
+
Args:
|
| 682 |
+
x (torch.Tensor): Input tensor.
|
| 683 |
+
|
| 684 |
+
Returns:
|
| 685 |
+
Tuple[torch.Tensor, torch.Tensor]: Routing weights and selected expert indices.
|
| 686 |
+
"""
|
| 687 |
+
scores = linear(x.float(), self.weight.float())
|
| 688 |
+
if self.score_func == "softmax":
|
| 689 |
+
scores = scores.softmax(dim=-1)
|
| 690 |
+
else:
|
| 691 |
+
scores = scores.sigmoid()
|
| 692 |
+
original_scores = scores
|
| 693 |
+
if self.bias is not None:
|
| 694 |
+
scores = scores + self.bias
|
| 695 |
+
if self.n_groups > 1:
|
| 696 |
+
scores = scores.view(x.size(0), self.n_groups, -1)
|
| 697 |
+
if self.bias is None:
|
| 698 |
+
group_scores = scores.amax(dim=-1)
|
| 699 |
+
else:
|
| 700 |
+
group_scores = scores.topk(2, dim=-1)[0].sum(dim=-1)
|
| 701 |
+
indices = group_scores.topk(self.topk_groups, dim=-1)[1]
|
| 702 |
+
mask = scores.new_ones(x.size(0), self.n_groups, dtype=bool).scatter_(1, indices, False)
|
| 703 |
+
scores = scores.masked_fill_(mask.unsqueeze(-1), float("-inf")).flatten(1)
|
| 704 |
+
indices = scores.topk(self.topk, dim=-1)[1]
|
| 705 |
+
weights = original_scores.gather(1, indices)
|
| 706 |
+
if self.score_func == "sigmoid":
|
| 707 |
+
weights /= weights.sum(dim=-1, keepdim=True)
|
| 708 |
+
weights *= self.route_scale
|
| 709 |
+
return weights, indices
|
| 710 |
+
|
| 711 |
+
|
| 712 |
+
class Expert(nn.Module):
|
| 713 |
+
"""
|
| 714 |
+
Expert layer for Mixture-of-Experts (MoE) models.
|
| 715 |
+
|
| 716 |
+
Attributes:
|
| 717 |
+
w1 (nn.Module): Linear layer for input-to-hidden transformation.
|
| 718 |
+
w2 (nn.Module): Linear layer for hidden-to-output transformation.
|
| 719 |
+
w3 (nn.Module): Additional linear layer for feature transformation.
|
| 720 |
+
"""
|
| 721 |
+
def __init__(self, dim: int, inter_dim: int):
|
| 722 |
+
"""
|
| 723 |
+
Initializes the Expert layer.
|
| 724 |
+
|
| 725 |
+
Args:
|
| 726 |
+
dim (int): Input and output dimensionality.
|
| 727 |
+
inter_dim (int): Hidden layer dimensionality.
|
| 728 |
+
"""
|
| 729 |
+
super().__init__()
|
| 730 |
+
self.w1 = Linear(dim, inter_dim)
|
| 731 |
+
self.w2 = Linear(inter_dim, dim)
|
| 732 |
+
self.w3 = Linear(dim, inter_dim)
|
| 733 |
+
|
| 734 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 735 |
+
"""
|
| 736 |
+
Forward pass for the Expert layer.
|
| 737 |
+
|
| 738 |
+
Args:
|
| 739 |
+
x (torch.Tensor): Input tensor.
|
| 740 |
+
|
| 741 |
+
Returns:
|
| 742 |
+
torch.Tensor: Output tensor after expert computation.
|
| 743 |
+
"""
|
| 744 |
+
return self.w2((F.silu(self.w1(x).float()) * self.w3(x).float()).type_as(x))
|
| 745 |
+
|
| 746 |
+
|
| 747 |
+
class MoE(nn.Module):
|
| 748 |
+
"""
|
| 749 |
+
Mixture-of-Experts (MoE) module.
|
| 750 |
+
|
| 751 |
+
Attributes:
|
| 752 |
+
dim (int): Dimensionality of input features.
|
| 753 |
+
n_routed_experts (int): Total number of experts in the model.
|
| 754 |
+
n_local_experts (int): Number of experts handled locally in distributed systems.
|
| 755 |
+
n_activated_experts (int): Number of experts activated for each input.
|
| 756 |
+
gate (nn.Module): Gating mechanism to route inputs to experts.
|
| 757 |
+
experts (nn.ModuleList): List of expert modules.
|
| 758 |
+
shared_experts (nn.Module): Shared experts applied to all inputs.
|
| 759 |
+
"""
|
| 760 |
+
def __init__(self, args: ModelArgs):
|
| 761 |
+
"""
|
| 762 |
+
Initializes the MoE module.
|
| 763 |
+
|
| 764 |
+
Args:
|
| 765 |
+
args (ModelArgs): Model arguments containing MoE parameters.
|
| 766 |
+
"""
|
| 767 |
+
super().__init__()
|
| 768 |
+
self.dim = args.dim
|
| 769 |
+
assert args.n_routed_experts % world_size == 0, f"Number of experts must be divisible by world size (world_size={world_size})"
|
| 770 |
+
self.n_routed_experts = args.n_routed_experts
|
| 771 |
+
self.n_local_experts = args.n_routed_experts // world_size
|
| 772 |
+
self.n_activated_experts = args.n_activated_experts
|
| 773 |
+
self.experts_start_idx = rank * self.n_local_experts
|
| 774 |
+
self.experts_end_idx = self.experts_start_idx + self.n_local_experts
|
| 775 |
+
self.gate = Gate(args)
|
| 776 |
+
self.experts = nn.ModuleList([Expert(args.dim, args.moe_inter_dim) if self.experts_start_idx <= i < self.experts_end_idx else None
|
| 777 |
+
for i in range(self.n_routed_experts)])
|
| 778 |
+
self.shared_experts = MLP(args.dim, args.n_shared_experts * args.moe_inter_dim, reduce_output=False)
|
| 779 |
+
|
| 780 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 781 |
+
"""
|
| 782 |
+
Forward pass for the MoE module.
|
| 783 |
+
|
| 784 |
+
Args:
|
| 785 |
+
x (torch.Tensor): Input tensor.
|
| 786 |
+
|
| 787 |
+
Returns:
|
| 788 |
+
torch.Tensor: Output tensor after expert routing and computation.
|
| 789 |
+
"""
|
| 790 |
+
shape = x.size()
|
| 791 |
+
x = x.view(-1, self.dim)
|
| 792 |
+
weights, indices = self.gate(x)
|
| 793 |
+
y = torch.zeros_like(x, dtype=torch.float32)
|
| 794 |
+
counts = torch.bincount(indices.flatten(), minlength=self.n_routed_experts).tolist()
|
| 795 |
+
for i in range(self.experts_start_idx, self.experts_end_idx):
|
| 796 |
+
if counts[i] == 0:
|
| 797 |
+
continue
|
| 798 |
+
expert = self.experts[i]
|
| 799 |
+
idx, top = torch.where(indices == i)
|
| 800 |
+
y[idx] += expert(x[idx]) * weights[idx, top, None]
|
| 801 |
+
y += self.shared_experts(x)
|
| 802 |
+
if world_size > 1:
|
| 803 |
+
dist.all_reduce(y)
|
| 804 |
+
return y.type_as(x).view(shape)
|
| 805 |
+
|
| 806 |
+
|
| 807 |
+
class Block(nn.Module):
|
| 808 |
+
"""
|
| 809 |
+
Transformer block combining attention and feed-forward layers.
|
| 810 |
+
|
| 811 |
+
Attributes:
|
| 812 |
+
attn (nn.Module): Attention layer (MLA).
|
| 813 |
+
ffn (nn.Module): Feed-forward network (MLP or MoE).
|
| 814 |
+
attn_norm (nn.Module): Layer normalization for attention.
|
| 815 |
+
ffn_norm (nn.Module): Layer normalization for feed-forward network.
|
| 816 |
+
"""
|
| 817 |
+
def __init__(self, layer_id: int, args: ModelArgs):
|
| 818 |
+
"""
|
| 819 |
+
Initializes the Transformer block.
|
| 820 |
+
|
| 821 |
+
Args:
|
| 822 |
+
layer_id (int): Layer index in the transformer.
|
| 823 |
+
args (ModelArgs): Model arguments containing block parameters.
|
| 824 |
+
"""
|
| 825 |
+
super().__init__()
|
| 826 |
+
self.attn = MLA(args)
|
| 827 |
+
self.ffn = MLP(args.dim, args.inter_dim) if layer_id < args.n_dense_layers else MoE(args)
|
| 828 |
+
self.attn_norm = RMSNorm(args.dim)
|
| 829 |
+
self.ffn_norm = RMSNorm(args.dim)
|
| 830 |
+
|
| 831 |
+
def forward(self, x: torch.Tensor, residual: torch.Tensor, start_pos: int, freqs_cis: torch.Tensor, mask: Optional[torch.Tensor]) -> torch.Tensor:
|
| 832 |
+
"""
|
| 833 |
+
Forward pass for the Transformer block.
|
| 834 |
+
|
| 835 |
+
Args:
|
| 836 |
+
x (torch.Tensor): Input tensor.
|
| 837 |
+
start_pos (int): Starting position in the sequence.
|
| 838 |
+
freqs_cis (torch.Tensor): Precomputed complex exponential values for rotary embeddings.
|
| 839 |
+
mask (Optional[torch.Tensor]): Mask tensor to exclude certain positions from attention.
|
| 840 |
+
|
| 841 |
+
Returns:
|
| 842 |
+
torch.Tensor: Output tensor after block computation.
|
| 843 |
+
"""
|
| 844 |
+
if residual is None:
|
| 845 |
+
x, residual = self.attn_norm(x), x
|
| 846 |
+
else:
|
| 847 |
+
x, residual = self.attn_norm(x, residual)
|
| 848 |
+
x = self.attn(x, start_pos, freqs_cis, mask)
|
| 849 |
+
x, residual = self.ffn_norm(x, residual)
|
| 850 |
+
x = self.ffn(x)
|
| 851 |
+
return x, residual
|
| 852 |
+
|
| 853 |
+
|
| 854 |
+
class Transformer(nn.Module):
|
| 855 |
+
"""
|
| 856 |
+
Transformer model with positional embeddings, multiple layers, and output projection.
|
| 857 |
+
|
| 858 |
+
Attributes:
|
| 859 |
+
max_seq_len (int): Maximum sequence length for the transformer.
|
| 860 |
+
embed (nn.Module): Embedding layer for input tokens.
|
| 861 |
+
layers (torch.nn.ModuleList): List of transformer blocks.
|
| 862 |
+
norm (nn.Module): Layer normalization applied after all blocks.
|
| 863 |
+
head (nn.Module): Output projection layer mapping to vocabulary size.
|
| 864 |
+
freqs_cis (torch.Tensor): Precomputed complex exponential values for rotary embeddings.
|
| 865 |
+
"""
|
| 866 |
+
def __init__(self, args: ModelArgs):
|
| 867 |
+
"""
|
| 868 |
+
Initializes the Transformer model.
|
| 869 |
+
|
| 870 |
+
Args:
|
| 871 |
+
args (ModelArgs): Model arguments containing transformer parameters.
|
| 872 |
+
"""
|
| 873 |
+
global world_size, rank
|
| 874 |
+
world_size = dist.get_world_size() if dist.is_initialized() else 1
|
| 875 |
+
rank = dist.get_rank() if dist.is_initialized() else 0
|
| 876 |
+
Linear.dtype = torch.float8_e4m3fn if args.dtype == "fp8" else torch.bfloat16
|
| 877 |
+
Linear.scale_fmt = args.scale_fmt
|
| 878 |
+
super().__init__()
|
| 879 |
+
self.max_seq_len = args.max_seq_len
|
| 880 |
+
self.embed = ParallelEmbedding(args.vocab_size, args.dim)
|
| 881 |
+
self.layers = torch.nn.ModuleList()
|
| 882 |
+
for layer_id in range(args.n_layers):
|
| 883 |
+
self.layers.append(Block(layer_id, args))
|
| 884 |
+
self.norm = RMSNorm(args.dim)
|
| 885 |
+
# lm_head in the checkpoint is stored in bf16, while the parameter here is stored in fp32 for easier computation of logits later.
|
| 886 |
+
self.head = ColumnParallelLinear(args.dim, args.vocab_size, dtype=torch.float32)
|
| 887 |
+
self.register_buffer("freqs_cis", precompute_freqs_cis(args), persistent=False)
|
| 888 |
+
|
| 889 |
+
@torch.inference_mode()
|
| 890 |
+
def forward(self, tokens: torch.Tensor, start_pos: int = 0):
|
| 891 |
+
"""
|
| 892 |
+
Forward pass for the Transformer model.
|
| 893 |
+
|
| 894 |
+
Args:
|
| 895 |
+
tokens (torch.Tensor): Input tensor of token IDs with shape (batch_size, seq_len).
|
| 896 |
+
start_pos (int, optional): Starting position in the sequence for rotary embeddings. Defaults to 0.
|
| 897 |
+
|
| 898 |
+
Returns:
|
| 899 |
+
torch.Tensor: Logits tensor of shape (batch_size, vocab_size).
|
| 900 |
+
"""
|
| 901 |
+
seqlen = tokens.size(1)
|
| 902 |
+
freqs_cis = self.freqs_cis[start_pos:start_pos+seqlen]
|
| 903 |
+
mask = torch.full((seqlen, seqlen), float("-inf"), device=tokens.device).triu_(1) if seqlen > 1 else None
|
| 904 |
+
h, residual = self.embed(tokens), None
|
| 905 |
+
for layer in self.layers:
|
| 906 |
+
h, residual = layer(h, residual, start_pos, freqs_cis, mask)
|
| 907 |
+
h, _ = self.norm(h, residual)
|
| 908 |
+
logits = self.head(h[:, -1].float())
|
| 909 |
+
if world_size > 1:
|
| 910 |
+
all_logits = [torch.empty_like(logits) for _ in range(world_size)]
|
| 911 |
+
dist.all_gather(all_logits, logits)
|
| 912 |
+
logits = torch.cat(all_logits, dim=-1)
|
| 913 |
+
return logits
|
| 914 |
+
|
| 915 |
+
|
| 916 |
+
if __name__ == "__main__":
|
| 917 |
+
torch.set_default_dtype(torch.bfloat16)
|
| 918 |
+
torch.set_default_device("cuda")
|
| 919 |
+
torch.manual_seed(0)
|
| 920 |
+
args = ModelArgs()
|
| 921 |
+
x = torch.randint(0, args.vocab_size, (2, 128))
|
| 922 |
+
model = Transformer(args)
|
| 923 |
+
print(model(x).size())
|
inference/requirements.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
torch
|
| 2 |
+
transformers
|
| 3 |
+
safetensors
|
| 4 |
+
fast_hadamard_transform
|
| 5 |
+
tilelang==0.1.6
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4fcfa230a056cd38141645b3ac3cff784d610bf63f8ee98528d38dc4bf0760ae
|
| 3 |
+
size 8305696
|
modeling_deepseek_v32.py
ADDED
|
@@ -0,0 +1,935 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2026 the HuggingFace Team. All rights reserved.
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
import math
|
| 17 |
+
from collections.abc import Callable
|
| 18 |
+
from typing import Optional
|
| 19 |
+
|
| 20 |
+
import torch
|
| 21 |
+
import torch.nn as nn
|
| 22 |
+
import torch.nn.functional as F
|
| 23 |
+
|
| 24 |
+
from transformers.activations import ACT2FN
|
| 25 |
+
from transformers.cache_utils import Cache, DynamicCache
|
| 26 |
+
from transformers.generation import GenerationMixin
|
| 27 |
+
from transformers.masking_utils import create_causal_mask
|
| 28 |
+
from transformers.modeling_flash_attention_utils import FlashAttentionKwargs
|
| 29 |
+
from transformers.modeling_layers import GradientCheckpointingLayer
|
| 30 |
+
from transformers.modeling_outputs import BaseModelOutputWithPast, CausalLMOutputWithPast
|
| 31 |
+
from transformers.modeling_rope_utils import ROPE_INIT_FUNCTIONS, dynamic_rope_update
|
| 32 |
+
from transformers.modeling_utils import ALL_ATTENTION_FUNCTIONS, PreTrainedModel
|
| 33 |
+
from transformers.processing_utils import Unpack
|
| 34 |
+
from transformers.utils import TransformersKwargs, can_return_tuple, logging
|
| 35 |
+
from transformers.utils.generic import check_model_inputs
|
| 36 |
+
from .configuration_deepseek_v32 import DeepseekV32Config
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
logger = logging.get_logger(__name__)
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
class DeepseekV32RMSNorm(nn.Module):
|
| 43 |
+
def __init__(self, hidden_size, eps: float = 1e-6) -> None:
|
| 44 |
+
"""
|
| 45 |
+
DeepseekV32RMSNorm is equivalent to T5LayerNorm
|
| 46 |
+
"""
|
| 47 |
+
super().__init__()
|
| 48 |
+
self.weight = nn.Parameter(torch.ones(hidden_size))
|
| 49 |
+
self.variance_epsilon = eps
|
| 50 |
+
|
| 51 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 52 |
+
input_dtype = hidden_states.dtype
|
| 53 |
+
hidden_states = hidden_states.to(torch.float32)
|
| 54 |
+
variance = hidden_states.pow(2).mean(-1, keepdim=True)
|
| 55 |
+
hidden_states = hidden_states * torch.rsqrt(variance + self.variance_epsilon)
|
| 56 |
+
return self.weight * hidden_states.to(input_dtype)
|
| 57 |
+
|
| 58 |
+
def extra_repr(self):
|
| 59 |
+
return f"{tuple(self.weight.shape)}, eps={self.variance_epsilon}"
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def apply_rotary_pos_emb(q, k, cos, sin, unsqueeze_dim=1):
|
| 63 |
+
"""Applies Rotary Position Embedding to the query and key tensors.
|
| 64 |
+
|
| 65 |
+
Args:
|
| 66 |
+
q (`torch.Tensor`): The query tensor.
|
| 67 |
+
k (`torch.Tensor`): The key tensor.
|
| 68 |
+
cos (`torch.Tensor`): The cosine part of the rotary embedding.
|
| 69 |
+
sin (`torch.Tensor`): The sine part of the rotary embedding.
|
| 70 |
+
unsqueeze_dim (`int`, *optional*, defaults to 1):
|
| 71 |
+
The 'unsqueeze_dim' argument specifies the dimension along which to unsqueeze cos[position_ids] and
|
| 72 |
+
sin[position_ids] so that they can be properly broadcasted to the dimensions of q and k. For example, note
|
| 73 |
+
that cos[position_ids] and sin[position_ids] have the shape [batch_size, seq_len, head_dim]. Then, if q and
|
| 74 |
+
k have the shape [batch_size, heads, seq_len, head_dim], then setting unsqueeze_dim=1 makes
|
| 75 |
+
cos[position_ids] and sin[position_ids] broadcastable to the shapes of q and k. Similarly, if q and k have
|
| 76 |
+
the shape [batch_size, seq_len, heads, head_dim], then set unsqueeze_dim=2.
|
| 77 |
+
Returns:
|
| 78 |
+
`tuple(torch.Tensor)` comprising of the query and key tensors rotated using the Rotary Position Embedding.
|
| 79 |
+
"""
|
| 80 |
+
cos = cos.unsqueeze(unsqueeze_dim)
|
| 81 |
+
sin = sin.unsqueeze(unsqueeze_dim)
|
| 82 |
+
q_embed = (q * cos) + (rotate_half(q) * sin)
|
| 83 |
+
k_embed = (k * cos) + (rotate_half(k) * sin)
|
| 84 |
+
return q_embed, k_embed
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
def rotate_half(x):
|
| 88 |
+
"""Rotates half the hidden dims of the input."""
|
| 89 |
+
x1 = x[..., : x.shape[-1] // 2]
|
| 90 |
+
x2 = x[..., x.shape[-1] // 2 :]
|
| 91 |
+
return torch.cat((-x2, x1), dim=-1)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def apply_rotary_pos_emb_interleave(q, k, cos, sin, position_ids=None, unsqueeze_dim=1):
|
| 95 |
+
r"""
|
| 96 |
+
TODO let's just use the original freqcis computation to not have the view
|
| 97 |
+
transpose + reshape! This is not optimized!
|
| 98 |
+
Applies Rotary Position Embedding to the query and key tensors.
|
| 99 |
+
|
| 100 |
+
Args:
|
| 101 |
+
q (`torch.Tensor`): The query tensor.
|
| 102 |
+
k (`torch.Tensor`): The key tensor.
|
| 103 |
+
cos (`torch.Tensor`): The cosine part of the rotary embedding.
|
| 104 |
+
sin (`torch.Tensor`): The sine part of the rotary embedding.
|
| 105 |
+
position_ids (`torch.Tensor`):
|
| 106 |
+
The position indices of the tokens corresponding to the query and key tensors. For example, this can be
|
| 107 |
+
used to pass offsetted position ids when working with a KV-cache.
|
| 108 |
+
unsqueeze_dim (`int`, *optional*, defaults to 1):
|
| 109 |
+
The 'unsqueeze_dim' argument specifies the dimension along which to unsqueeze cos[position_ids] and
|
| 110 |
+
sin[position_ids] so that they can be properly broadcasted to the dimensions of q and k. For example, note
|
| 111 |
+
that cos[position_ids] and sin[position_ids] have the shape [batch_size, seq_len, head_dim]. Then, if q and
|
| 112 |
+
k have the shape [batch_size, heads, seq_len, head_dim], then setting unsqueeze_dim=1 makes
|
| 113 |
+
cos[position_ids] and sin[position_ids] broadcastable to the shapes of q and k. Similarly, if q and k have
|
| 114 |
+
the shape [batch_size, seq_len, heads, head_dim], then set unsqueeze_dim=2.
|
| 115 |
+
Returns:
|
| 116 |
+
`tuple(torch.Tensor)` comprising of the query and key tensors rotated using the Rotary Position Embedding.
|
| 117 |
+
"""
|
| 118 |
+
cos = cos.unsqueeze(unsqueeze_dim)
|
| 119 |
+
sin = sin.unsqueeze(unsqueeze_dim)
|
| 120 |
+
|
| 121 |
+
b, h, s, d = q.shape
|
| 122 |
+
q = q.view(b, h, s, d // 2, 2).transpose(4, 3).reshape(b, h, s, d)
|
| 123 |
+
|
| 124 |
+
b, h, s, d = k.shape
|
| 125 |
+
k = k.view(b, h, s, d // 2, 2).transpose(4, 3).reshape(b, h, s, d)
|
| 126 |
+
|
| 127 |
+
q_embed = (q * cos) + (rotate_half(q) * sin)
|
| 128 |
+
k_embed = (k * cos) + (rotate_half(k) * sin)
|
| 129 |
+
return q_embed, k_embed
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
def yarn_get_mscale(scale=1, mscale=1):
|
| 133 |
+
if scale <= 1:
|
| 134 |
+
return 1.0
|
| 135 |
+
return 0.1 * mscale * math.log(scale) + 1.0
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def repeat_kv(hidden_states: torch.Tensor, n_rep: int) -> torch.Tensor:
|
| 139 |
+
"""
|
| 140 |
+
This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
|
| 141 |
+
num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
|
| 142 |
+
"""
|
| 143 |
+
batch, num_key_value_heads, slen, head_dim = hidden_states.shape
|
| 144 |
+
if n_rep == 1:
|
| 145 |
+
return hidden_states
|
| 146 |
+
hidden_states = hidden_states[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
|
| 147 |
+
return hidden_states.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
def eager_attention_forward(
|
| 151 |
+
module: nn.Module,
|
| 152 |
+
query: torch.Tensor,
|
| 153 |
+
key: torch.Tensor,
|
| 154 |
+
value: torch.Tensor,
|
| 155 |
+
attention_mask: torch.Tensor | None,
|
| 156 |
+
scaling: float,
|
| 157 |
+
dropout: float = 0.0,
|
| 158 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 159 |
+
):
|
| 160 |
+
key_states = repeat_kv(key, module.num_key_value_groups)
|
| 161 |
+
value_states = repeat_kv(value, module.num_key_value_groups)
|
| 162 |
+
|
| 163 |
+
attn_weights = torch.matmul(query, key_states.transpose(2, 3)) * scaling
|
| 164 |
+
if attention_mask is not None:
|
| 165 |
+
causal_mask = attention_mask[:, :, :, : key_states.shape[-2]]
|
| 166 |
+
attn_weights = attn_weights + causal_mask
|
| 167 |
+
|
| 168 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1, dtype=torch.float32).to(query.dtype)
|
| 169 |
+
attn_weights = nn.functional.dropout(attn_weights, p=dropout, training=module.training)
|
| 170 |
+
attn_output = torch.matmul(attn_weights, value_states)
|
| 171 |
+
attn_output = attn_output.transpose(1, 2).contiguous()
|
| 172 |
+
|
| 173 |
+
return attn_output, attn_weights
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
class DeepseekV32Indexer(nn.Module):
|
| 177 |
+
def __init__(self, config: "DeepseekV32Config", index_layer_idx: int):
|
| 178 |
+
super().__init__()
|
| 179 |
+
self.config = config
|
| 180 |
+
self.layer_idx = index_layer_idx
|
| 181 |
+
|
| 182 |
+
self.hidden_size: int = config.hidden_size
|
| 183 |
+
self.num_heads: int = config.index_n_heads
|
| 184 |
+
self.num_local_heads: int = config.index_n_heads # world_size handling can be added as needed
|
| 185 |
+
self.head_dim: int = config.index_head_dim
|
| 186 |
+
self.qk_rope_head_dim: int = config.qk_rope_head_dim
|
| 187 |
+
self.index_topk: int = config.index_topk
|
| 188 |
+
self.q_lora_rank: int = config.q_lora_rank
|
| 189 |
+
|
| 190 |
+
self.wq_b = nn.Linear(self.q_lora_rank, self.num_heads * self.head_dim, bias=False)
|
| 191 |
+
self.wk = nn.Linear(self.hidden_size, self.head_dim, bias=False)
|
| 192 |
+
self.k_norm = nn.LayerNorm(self.head_dim)
|
| 193 |
+
self.weights_proj = nn.Linear(self.hidden_size, self.num_heads, dtype=torch.get_default_dtype(), bias=False)
|
| 194 |
+
self.softmax_scale = self.head_dim**-0.5
|
| 195 |
+
|
| 196 |
+
@torch.no_grad()
|
| 197 |
+
def forward(
|
| 198 |
+
self,
|
| 199 |
+
hidden_states: torch.Tensor, # [B, S, hidden]
|
| 200 |
+
q_resid: torch.Tensor, # [B, S, q_lora_rank]
|
| 201 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
| 202 |
+
attention_mask: torch.Tensor | None,
|
| 203 |
+
past_key_values_index: "Cache",
|
| 204 |
+
cache_position: torch.LongTensor | None,
|
| 205 |
+
) -> torch.LongTensor:
|
| 206 |
+
B, S, _ = hidden_states.shape
|
| 207 |
+
cos, sin = position_embeddings
|
| 208 |
+
|
| 209 |
+
# Queries
|
| 210 |
+
q_states = self.wq_bj(q_resid) # [B, S, H*D]
|
| 211 |
+
q_states = q_states.view(B, S, self.num_heads, self.head_dim) # [B, S, H, D]
|
| 212 |
+
q_rot, q_pass = torch.split(q_states, [self.qk_rope_head_dim, self.head_dim - self.qk_rope_head_dim], dim=-1)
|
| 213 |
+
q_rot = apply_rotary_pos_emb_interleave(q_rot, cos, sin) # [B, S, H, rope_D]
|
| 214 |
+
q_states = torch.cat([q_rot, q_pass], dim=-1) # [B, S, H, D]
|
| 215 |
+
|
| 216 |
+
# Keys
|
| 217 |
+
k = self.k_norm(self.wk(hidden_states)) # [B, S, D]
|
| 218 |
+
k_rot, k_pass = torch.split(k, [self.qk_rope_head_dim, self.head_dim - self.qk_rope_head_dim], dim=-1)
|
| 219 |
+
# MLA uses single-head rope stream, then expands later; keep [B, 1, S, rope_D] here
|
| 220 |
+
k_rot = k_rot.unsqueeze(1) # [B, 1, S, rope_D]
|
| 221 |
+
k_rot = apply_rotary_pos_emb_interleave(k_rot, cos, sin) # [B, 1, S, rope_D]
|
| 222 |
+
k_states = torch.cat(
|
| 223 |
+
[
|
| 224 |
+
k_rot.expand(B, self.num_heads, S, -1), # expand rope
|
| 225 |
+
k_pass.view(B, 1, S, -1).expand(B, self.num_heads, S, -1),
|
| 226 |
+
],
|
| 227 |
+
dim=-1,
|
| 228 |
+
) # [B, H, S, D]
|
| 229 |
+
|
| 230 |
+
# Quantize (per provided utilities)
|
| 231 |
+
# Update indexer cache (layer idx belongs to the attention layer using this indexer)
|
| 232 |
+
# We store as: keys = k_fp8 (as [B, 1, S, D] or [B, H, S, D]? We keep [B, 1, S, D] like original)
|
| 233 |
+
# For compactness, collapse heads to 1 for the indexer (you can keep H if your fp8_index expects it).
|
| 234 |
+
k_1h = k_states.mean(dim=1, keepdim=True) # [B, 1, S, D] (cheap head merge; adjust if needed)
|
| 235 |
+
k_cache = past_key_values_index.update(k_1h, self.layer_idx, cache_kwargs={"cache_position": cache_position})
|
| 236 |
+
|
| 237 |
+
# Weights per head
|
| 238 |
+
head_weights = self.weights_proj(hidden_states) * (self.num_heads**-0.5) # [B, S, H]
|
| 239 |
+
head_weights = head_weights.unsqueeze(-1) * self.softmax_scale # [B, S, H, *]
|
| 240 |
+
logits = torch.matmul(k_cache.unsqueeze(1), q_states.transpose(-1, -2)) # [B, M, N, H]
|
| 241 |
+
|
| 242 |
+
# ReLU and sum over heads -> [B, M, N]
|
| 243 |
+
logits.clamp_min_(0)
|
| 244 |
+
index_scores = logits.sum(dim=-1) # [B, M, N]
|
| 245 |
+
|
| 246 |
+
if attention_mask is not None:
|
| 247 |
+
index_scores = index_scores + attention_mask
|
| 248 |
+
|
| 249 |
+
T = index_scores.shape[-1]
|
| 250 |
+
topk = min(self.index_topk, T)
|
| 251 |
+
topk_indices = index_scores.topk(topk, dim=-1).indices # [..., topk]
|
| 252 |
+
return topk_indices
|
| 253 |
+
|
| 254 |
+
class DeepseekV32Attention(nn.Module):
|
| 255 |
+
"""
|
| 256 |
+
DeepSeek V3.2 sparse attention mechanism with indexer.
|
| 257 |
+
|
| 258 |
+
This implements the native sparse attention from [DeepSeek V3.2](https://huggingface.co/deepseek-ai/DeepSeek-V3.2) which uses
|
| 259 |
+
an indexer to select top-k tokens for attention computation, making it more efficient for long sequences.
|
| 260 |
+
"""
|
| 261 |
+
|
| 262 |
+
def __init__(self, config: DeepseekV32Config, layer_idx: int):
|
| 263 |
+
super().__init__()
|
| 264 |
+
self.config = config
|
| 265 |
+
self.layer_idx = layer_idx
|
| 266 |
+
self.num_key_value_groups = config.num_attention_heads // config.num_key_value_heads
|
| 267 |
+
self.attention_dropout = config.attention_dropout
|
| 268 |
+
self.num_heads = config.num_attention_heads
|
| 269 |
+
|
| 270 |
+
self.q_lora_rank = config.q_lora_rank
|
| 271 |
+
self.qk_rope_head_dim = config.qk_rope_head_dim
|
| 272 |
+
self.kv_lora_rank = config.kv_lora_rank
|
| 273 |
+
self.v_head_dim = config.v_head_dim
|
| 274 |
+
self.qk_nope_head_dim = config.qk_nope_head_dim
|
| 275 |
+
self.qk_head_dim = config.qk_head_dim
|
| 276 |
+
self.index_topk = config.index_topk
|
| 277 |
+
|
| 278 |
+
self.is_causal = True
|
| 279 |
+
|
| 280 |
+
# Query projection
|
| 281 |
+
if self.q_lora_rank is None:
|
| 282 |
+
self.q_proj = nn.Linear(config.hidden_size, self.num_heads * self.qk_head_dim, bias=False)
|
| 283 |
+
else:
|
| 284 |
+
self.q_a_proj = nn.Linear(config.hidden_size, config.q_lora_rank, bias=config.attention_bias)
|
| 285 |
+
self.q_a_layernorm = DeepseekV32RMSNorm(config.q_lora_rank)
|
| 286 |
+
self.q_b_proj = nn.Linear(config.q_lora_rank, self.num_heads * self.qk_head_dim, bias=False)
|
| 287 |
+
|
| 288 |
+
# Key-Value projections
|
| 289 |
+
self.kv_a_proj_with_mqa = nn.Linear(
|
| 290 |
+
config.hidden_size,
|
| 291 |
+
self.kv_lora_rank + self.qk_rope_head_dim,
|
| 292 |
+
bias=config.attention_bias,
|
| 293 |
+
)
|
| 294 |
+
self.kv_a_layernorm = DeepseekV32RMSNorm(self.kv_lora_rank)
|
| 295 |
+
self.kv_b_proj = nn.Linear(
|
| 296 |
+
self.kv_lora_rank,
|
| 297 |
+
self.num_heads * (self.qk_nope_head_dim + self.v_head_dim),
|
| 298 |
+
bias=False,
|
| 299 |
+
)
|
| 300 |
+
|
| 301 |
+
# Output projection
|
| 302 |
+
self.o_proj = nn.Linear(
|
| 303 |
+
self.num_heads * self.v_head_dim,
|
| 304 |
+
config.hidden_size,
|
| 305 |
+
bias=config.attention_bias,
|
| 306 |
+
)
|
| 307 |
+
|
| 308 |
+
# Indexer components for sparse attention
|
| 309 |
+
self.wq_b = nn.Linear(config.q_lora_rank, self.num_heads * self.qk_head_dim, bias=False)
|
| 310 |
+
self.wk = nn.Linear(config.hidden_size, self.qk_head_dim, bias=config.attention_bias)
|
| 311 |
+
self.k_norm = DeepseekV32RMSNorm(self.qk_head_dim)
|
| 312 |
+
self.weights_proj = nn.Linear(config.hidden_size, self.num_heads, bias=False)
|
| 313 |
+
|
| 314 |
+
self.scaling = self.qk_head_dim ** (-0.5)
|
| 315 |
+
if self.config.rope_scaling.get("rope_type", "default") != "default":
|
| 316 |
+
mscale_all_dim = self.config.rope_scaling.get("mscale_all_dim", 0)
|
| 317 |
+
scaling_factor = self.config.rope_scaling["factor"]
|
| 318 |
+
if mscale_all_dim:
|
| 319 |
+
mscale = yarn_get_mscale(scaling_factor, mscale_all_dim)
|
| 320 |
+
self.scaling = self.scaling * mscale * mscale
|
| 321 |
+
|
| 322 |
+
self.indexer = DeepseekV32Indexer(config, layer_idx)
|
| 323 |
+
|
| 324 |
+
def forward(
|
| 325 |
+
self,
|
| 326 |
+
hidden_states: torch.Tensor,
|
| 327 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
| 328 |
+
attention_mask: torch.Tensor | None,
|
| 329 |
+
past_key_values: Cache | None = None,
|
| 330 |
+
cache_position: torch.LongTensor | None = None,
|
| 331 |
+
**kwargs: Unpack[FlashAttentionKwargs],
|
| 332 |
+
) -> tuple[torch.Tensor, torch.Tensor | None, tuple[torch.Tensor] | None]:
|
| 333 |
+
batch_size, seq_length = hidden_states.shape[:-1]
|
| 334 |
+
|
| 335 |
+
# For training or when index_topk is not effective, fall back to standard attention
|
| 336 |
+
# This is a simplified implementation - in practice, you'd implement the full sparse indexer
|
| 337 |
+
if self.training or seq_length <= self.index_topk:
|
| 338 |
+
logger.warning_once(
|
| 339 |
+
"DeepSeek V3.2 sparse attention is not fully implemented in this version. "
|
| 340 |
+
"Falling back to standard attention. For production use, please use vLLM or "
|
| 341 |
+
"other optimized inference engines.",
|
| 342 |
+
)
|
| 343 |
+
return self._standard_attention(
|
| 344 |
+
hidden_states, position_embeddings, attention_mask, past_key_values, cache_position, **kwargs
|
| 345 |
+
)
|
| 346 |
+
|
| 347 |
+
# Sparse attention implementation would go here
|
| 348 |
+
# This requires custom CUDA kernels for efficient top-k selection and indexing
|
| 349 |
+
return self._dsa_attention(
|
| 350 |
+
hidden_states, position_embeddings, attention_mask, past_key_values, cache_position, **kwargs
|
| 351 |
+
)
|
| 352 |
+
|
| 353 |
+
def _standard_attention(
|
| 354 |
+
self,
|
| 355 |
+
hidden_states: torch.Tensor,
|
| 356 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
| 357 |
+
attention_mask: torch.Tensor | None,
|
| 358 |
+
past_key_values: Cache | None = None,
|
| 359 |
+
cache_position: torch.LongTensor | None = None,
|
| 360 |
+
**kwargs: Unpack[FlashAttentionKwargs],
|
| 361 |
+
) -> tuple[torch.Tensor, torch.Tensor | None, tuple[torch.Tensor] | None]:
|
| 362 |
+
"""Standard attention fallback (same as DeepSeek V3)"""
|
| 363 |
+
batch_size, seq_length = hidden_states.shape[:-1]
|
| 364 |
+
query_shape = (batch_size, seq_length, -1, self.qk_head_dim)
|
| 365 |
+
key_shape = (batch_size, seq_length, -1, self.qk_nope_head_dim + self.v_head_dim)
|
| 366 |
+
|
| 367 |
+
if self.q_lora_rank is None:
|
| 368 |
+
q_states = self.q_proj(hidden_states)
|
| 369 |
+
else:
|
| 370 |
+
q_states = self.q_b_proj(self.q_a_layernorm(self.q_a_proj(hidden_states)))
|
| 371 |
+
q_states = q_states.view(query_shape).transpose(1, 2)
|
| 372 |
+
q_pass, q_rot = torch.split(q_states, [self.qk_nope_head_dim, self.qk_rope_head_dim], dim=-1)
|
| 373 |
+
|
| 374 |
+
compressed_kv = self.kv_a_proj_with_mqa(hidden_states)
|
| 375 |
+
k_pass, k_rot = torch.split(compressed_kv, [self.kv_lora_rank, self.qk_rope_head_dim], dim=-1)
|
| 376 |
+
|
| 377 |
+
k_pass = self.kv_b_proj(self.kv_a_layernorm(k_pass)).view(key_shape).transpose(1, 2)
|
| 378 |
+
k_pass, value_states = torch.split(k_pass, [self.qk_nope_head_dim, self.v_head_dim], dim=-1)
|
| 379 |
+
|
| 380 |
+
k_rot = k_rot.view(batch_size, 1, seq_length, self.qk_rope_head_dim)
|
| 381 |
+
|
| 382 |
+
cos, sin = position_embeddings
|
| 383 |
+
if self.config.rope_interleave:
|
| 384 |
+
q_rot, k_rot = apply_rotary_pos_emb_interleave(q_rot, k_rot, cos, sin)
|
| 385 |
+
else:
|
| 386 |
+
q_rot, k_rot = apply_rotary_pos_emb(q_rot, k_rot, cos, sin)
|
| 387 |
+
k_rot = k_rot.expand(*k_pass.shape[:-1], -1)
|
| 388 |
+
|
| 389 |
+
query_states = torch.cat((q_pass, q_rot), dim=-1)
|
| 390 |
+
key_states = torch.cat((k_pass, k_rot), dim=-1)
|
| 391 |
+
|
| 392 |
+
if past_key_values is not None:
|
| 393 |
+
cache_kwargs = {"sin": sin, "cos": cos, "cache_position": cache_position}
|
| 394 |
+
key_states, value_states = past_key_values.update(key_states, value_states, self.layer_idx, cache_kwargs)
|
| 395 |
+
|
| 396 |
+
if self.config._attn_implementation == "flash_attention_2" and self.qk_head_dim != self.v_head_dim:
|
| 397 |
+
value_states = F.pad(value_states, [0, self.qk_head_dim - self.v_head_dim])
|
| 398 |
+
|
| 399 |
+
attention_interface: Callable = ALL_ATTENTION_FUNCTIONS.get_interface(
|
| 400 |
+
self.config._attn_implementation, eager_attention_forward
|
| 401 |
+
)
|
| 402 |
+
|
| 403 |
+
attn_output, attn_weights = attention_interface(
|
| 404 |
+
self,
|
| 405 |
+
query_states,
|
| 406 |
+
key_states,
|
| 407 |
+
value_states,
|
| 408 |
+
attention_mask,
|
| 409 |
+
dropout=0.0 if not self.training else self.attention_dropout,
|
| 410 |
+
scaling=self.scaling,
|
| 411 |
+
**kwargs,
|
| 412 |
+
)
|
| 413 |
+
|
| 414 |
+
if self.config._attn_implementation == "flash_attention_2" and self.qk_head_dim != self.v_head_dim:
|
| 415 |
+
attn_output = attn_output[:, :, :, : self.v_head_dim]
|
| 416 |
+
|
| 417 |
+
attn_output = attn_output.reshape(batch_size, seq_length, -1).contiguous()
|
| 418 |
+
attn_output = self.o_proj(attn_output)
|
| 419 |
+
return attn_output, attn_weights
|
| 420 |
+
|
| 421 |
+
def _dsa_attention(
|
| 422 |
+
self,
|
| 423 |
+
hidden_states: torch.Tensor,
|
| 424 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
| 425 |
+
attention_mask: torch.Tensor | None,
|
| 426 |
+
past_key_values: Cache | None = None,
|
| 427 |
+
cache_position: torch.LongTensor | None = None,
|
| 428 |
+
**kwargs: Unpack[FlashAttentionKwargs]
|
| 429 |
+
):
|
| 430 |
+
|
| 431 |
+
B, S, _ = hidden_states.shape
|
| 432 |
+
cos, sin = position_embeddings
|
| 433 |
+
|
| 434 |
+
# ----- Q path -----
|
| 435 |
+
q_resid = self.q_a_layernorm(self.q_a_proj(hidden_states)) # [B, S, q_lora_rank]
|
| 436 |
+
q_states = self.q_b_proj(q_resid).view(B, S, self.num_heads, self.qk_head_dim) # [B, S, H, D]
|
| 437 |
+
# Split into pass/rot then apply RoPE on q_rot
|
| 438 |
+
q_pass, q_rot = torch.split(q_states, [self.qk_nope_head_dim, self.qk_rope_head_dim], dim=-1)
|
| 439 |
+
q_rot = apply_rotary_pos_emb(q_rot, cos, sin) # [B, S, H, rope_D]
|
| 440 |
+
q_states = torch.cat([q_pass, q_rot], dim=-1) # [B, S, H, D]
|
| 441 |
+
|
| 442 |
+
# Layout for matmul: [B, H, S, D]
|
| 443 |
+
q_states = q_states.transpose(1, 2).contiguous() # [B, H, S, D]
|
| 444 |
+
|
| 445 |
+
# ----- KV path (compressed + rope stream) -----
|
| 446 |
+
kv_all = self.kv_a_proj_with_mqa(hidden_states) # [B, S, kv_rank + rope_D]
|
| 447 |
+
kv_compressed, k_rot = torch.split(kv_all, [self.kv_lora_rank, self.qk_rope_head_dim], dim=-1)
|
| 448 |
+
kv_compressed = self.kv_a_layernorm(kv_compressed) # [B, S, kv_rank]
|
| 449 |
+
# Pre-project to K_pass and V
|
| 450 |
+
kv_proj = self.kv_b_proj(kv_compressed) # [B, S, H*(qk_nope + v)]
|
| 451 |
+
kv_proj = kv_proj.view(B, S, self.num_heads, self.qk_nope_head_dim + self.v_head_dim)
|
| 452 |
+
k_pass, v_states = torch.split(
|
| 453 |
+
kv_proj, [self.qk_nope_head_dim, self.v_head_dim], dim=-1
|
| 454 |
+
) # [B,S,H,nope], [B,S,H,V]
|
| 455 |
+
|
| 456 |
+
# Rope on K side: keep a single-head rope stream like MLA, then expand
|
| 457 |
+
k_rot = k_rot.view(B, 1, S, self.qk_rope_head_dim) # [B, 1, S, rope_D]
|
| 458 |
+
k_rot = apply_rotary_pos_emb(k_rot, cos, sin) # [B, 1, S, rope_D]
|
| 459 |
+
|
| 460 |
+
# Concatenate K = [K_pass, K_rot(expanded)]
|
| 461 |
+
k_states = torch.cat(
|
| 462 |
+
(
|
| 463 |
+
k_pass.transpose(1, 2), # [B, H, S, nope_D]
|
| 464 |
+
k_rot.expand(B, self.num_heads, S, -1),
|
| 465 |
+
), # [B, H, S, rope_D]
|
| 466 |
+
dim=-1,
|
| 467 |
+
) # [B, H, S, D]
|
| 468 |
+
v_states = v_states.transpose(1, 2).contiguous() # [B, H, S, V]
|
| 469 |
+
|
| 470 |
+
# ----- Cache update/usage -----
|
| 471 |
+
if past_key_values is not None:
|
| 472 |
+
# Store compressed stream & rope stream (as in original MLA path)
|
| 473 |
+
# We cache `kv_compressed` under `keys` and `k_rot` under `values` in MlaLayer.
|
| 474 |
+
# Shapes must be [B, H, t, *] and [B, 1, t, rope_D].
|
| 475 |
+
kv_comp_cache = kv_compressed.view(B, 1, S, self.kv_lora_rank).expand(B, self.num_heads, S, -1)
|
| 476 |
+
k_rot_cache = k_rot # [B, 1, S, rope_D]
|
| 477 |
+
cached_kv, cached_pe = past_key_values.update(
|
| 478 |
+
kv_comp_cache, k_rot_cache, layer_idx=self.layer_idx, cache_kwargs={"cache_position": cache_position}
|
| 479 |
+
)
|
| 480 |
+
# Decode path makes use of cached projections; Prefill can use full K/V directly.
|
| 481 |
+
|
| 482 |
+
# ----- Two paths (prefill vs decode) -----
|
| 483 |
+
if attention_mask is not None:
|
| 484 |
+
# Prefill (full attention over local window): standard scaled dot-product with top-k pruning from indexer
|
| 485 |
+
|
| 486 |
+
# Build scores: [B, H, S, S_total]
|
| 487 |
+
# K layout already [B, H, T, D]
|
| 488 |
+
scores = (q_states.float() @ k_states.float().transpose(-1, -2)) * self.scaling # [B, H, S, T]
|
| 489 |
+
|
| 490 |
+
# Indexer top-k
|
| 491 |
+
if past_key_values is not None:
|
| 492 |
+
topk_idx = self.indexer(
|
| 493 |
+
hidden_states,
|
| 494 |
+
q_resid,
|
| 495 |
+
position_embeddings,
|
| 496 |
+
attention_mask,
|
| 497 |
+
past_key_values_index=past_key_values, # we reuse same Cache with IndexerLayer? (separate cache recommended)
|
| 498 |
+
cache_position=cache_position,
|
| 499 |
+
)
|
| 500 |
+
# Build mask to keep only top-k per (B,S,head?)
|
| 501 |
+
# Expect topk_idx shape to broadcast to [B, H, S, T]. We scatter along last dim.
|
| 502 |
+
keep_mask = torch.full_like(scores, float("-inf"))
|
| 503 |
+
# If topk_idx is [B,S,topk], expand for heads:
|
| 504 |
+
if topk_idx.dim() == 3:
|
| 505 |
+
topk_idx = topk_idx.unsqueeze(1).expand(B, self.num_heads, S, -1)
|
| 506 |
+
keep_mask.scatter_(-1, topk_idx, 0.0)
|
| 507 |
+
scores = scores + keep_mask
|
| 508 |
+
|
| 509 |
+
probs = nn.functional.softmax(scores, dim=-1, dtype=torch.float32).type_as(hidden_states) # [B, H, S, T]
|
| 510 |
+
attn_output = probs @ v_states # [B, H, S, V]
|
| 511 |
+
|
| 512 |
+
elif past_key_values is not None:
|
| 513 |
+
# Decode: use cached compressed KV & rope stream to recompose attention scores efficiently
|
| 514 |
+
# Compose q_pass and q_rot pieces as in MLA math, but via matmul
|
| 515 |
+
# 1) Rebuild "nope" term via kv_b weights (dequant on the fly)
|
| 516 |
+
wkv_b = self.kv_b_proj.weight.view(
|
| 517 |
+
self.num_heads, self.qk_nope_head_dim + self.v_head_dim, self.kv_lora_rank
|
| 518 |
+
)
|
| 519 |
+
w_k_nope = wkv_b[:, : self.qk_nope_head_dim, :] # [H, nope_D, kv_rank]
|
| 520 |
+
w_v = wkv_b[:, self.qk_nope_head_dim :, :] # [H, V, kv_rank]
|
| 521 |
+
|
| 522 |
+
# q_pass: [B,H,S,nope_D]; cached_kv: [B,H,T,kv_rank]
|
| 523 |
+
q_pass = q_states[..., : self.qk_nope_head_dim] # [B,H,S,nope_D]
|
| 524 |
+
kv_comp = past_key_values[self.layer_idx][0] # keys -> [B,H,T,kv_rank]
|
| 525 |
+
pe_full = past_key_values[self.layer_idx][1] # values -> [B,1,T,rope_D]
|
| 526 |
+
# Project q_pass with w_k_nope: [B,H,S,kv_rank]
|
| 527 |
+
qk_nope = torch.matmul(q_pass, w_k_nope.transpose(-1, -2)) # [B,H,S,kv_rank]
|
| 528 |
+
# Scores_nope = qk_nope @ kv_comp^T
|
| 529 |
+
scores_nope = torch.matmul(qk_nope.float(), kv_comp.float().transpose(-1, -2)) # [B,H,S,T]
|
| 530 |
+
|
| 531 |
+
# 2) Rope term: q_rot @ k_rot^T
|
| 532 |
+
q_rot_only = q_states[..., -self.qk_rope_head_dim :] # [B,H,S,rope_D]
|
| 533 |
+
k_rot_only = pe_full.expand(B, self.num_heads, -1, -1) # [B,H,T,rope_D]
|
| 534 |
+
scores_rot = torch.matmul(q_rot_only.float(), k_rot_only.float().transpose(-1, -2)) # [B,H,S,T]
|
| 535 |
+
|
| 536 |
+
scores = (scores_nope + scores_rot) * self.scaling
|
| 537 |
+
|
| 538 |
+
# Indexer top-k (decode)
|
| 539 |
+
topk_idx = self.indexer(
|
| 540 |
+
hidden_states,
|
| 541 |
+
q_resid,
|
| 542 |
+
position_embeddings,
|
| 543 |
+
attention_mask,
|
| 544 |
+
past_key_values_index=past_key_values,
|
| 545 |
+
cache_position=cache_position,
|
| 546 |
+
)
|
| 547 |
+
# For decode single-step S==1 typically; build a [B,H,1,T] mask
|
| 548 |
+
keep_mask = torch.full_like(scores, float("-inf"))
|
| 549 |
+
if topk_idx.dim() == 3:
|
| 550 |
+
topk_idx = topk_idx.unsqueeze(1).expand(B, self.num_heads, S, -1)
|
| 551 |
+
keep_mask.scatter_(-1, topk_idx, 0.0)
|
| 552 |
+
scores = scores + keep_mask
|
| 553 |
+
|
| 554 |
+
probs = nn.functional.softmax(scores, dim=-1, dtype=torch.float32).type_as(hidden_states) # [B,H,S,T]
|
| 555 |
+
|
| 556 |
+
# Rebuild V for decode fast-path: v = (kv_comp @ w_v^T)
|
| 557 |
+
# kv_comp: [B,H,T,kv_rank], w_v: [H, V, kv_rank]
|
| 558 |
+
v_from_comp = torch.matmul(kv_comp, w_v.transpose(-1, -2)) # [B,H,T,V]
|
| 559 |
+
attn_output = torch.matmul(probs, v_from_comp) # [B,H,S,V]
|
| 560 |
+
|
| 561 |
+
# Output projection
|
| 562 |
+
attn_output = attn_output.transpose(1, 2).reshape(B, S, -1).contiguous() # [B,S,H*V]
|
| 563 |
+
attn_output = self.o_proj(attn_output) # [B,S,hidden]
|
| 564 |
+
return attn_output, None
|
| 565 |
+
|
| 566 |
+
|
| 567 |
+
|
| 568 |
+
class DeepseekV32MLP(nn.Module):
|
| 569 |
+
def __init__(self, config, intermediate_size=None):
|
| 570 |
+
super().__init__()
|
| 571 |
+
self.config = config
|
| 572 |
+
self.hidden_size = config.hidden_size
|
| 573 |
+
self.intermediate_size = config.intermediate_size if intermediate_size is None else intermediate_size
|
| 574 |
+
self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
| 575 |
+
self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
| 576 |
+
self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
|
| 577 |
+
self.act_fn = ACT2FN[config.hidden_act]
|
| 578 |
+
|
| 579 |
+
def forward(self, x):
|
| 580 |
+
down_proj = self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x))
|
| 581 |
+
return down_proj
|
| 582 |
+
|
| 583 |
+
|
| 584 |
+
class DeepseekV32TopkRouter(nn.Module):
|
| 585 |
+
def __init__(self, config: DeepseekV32Config):
|
| 586 |
+
super().__init__()
|
| 587 |
+
self.config = config
|
| 588 |
+
self.top_k = config.num_experts_per_tok
|
| 589 |
+
self.n_routed_experts = config.n_routed_experts
|
| 590 |
+
self.routed_scaling_factor = config.routed_scaling_factor
|
| 591 |
+
self.n_group = config.n_group
|
| 592 |
+
self.topk_group = config.topk_group
|
| 593 |
+
self.norm_topk_prob = config.norm_topk_prob
|
| 594 |
+
|
| 595 |
+
self.weight = nn.Parameter(torch.empty((self.n_routed_experts, config.hidden_size)))
|
| 596 |
+
self.register_buffer("e_score_correction_bias", torch.zeros((self.n_routed_experts), dtype=torch.float32))
|
| 597 |
+
|
| 598 |
+
def forward(self, hidden_states):
|
| 599 |
+
hidden_states = hidden_states.view(-1, self.config.hidden_size)
|
| 600 |
+
router_logits = F.linear(hidden_states.type(torch.float32), self.weight.type(torch.float32))
|
| 601 |
+
return router_logits
|
| 602 |
+
|
| 603 |
+
|
| 604 |
+
class DeepseekV32MoE(nn.Module):
|
| 605 |
+
"""
|
| 606 |
+
A mixed expert module containing shared experts.
|
| 607 |
+
"""
|
| 608 |
+
|
| 609 |
+
def __init__(self, config):
|
| 610 |
+
super().__init__()
|
| 611 |
+
self.config = config
|
| 612 |
+
self.experts = nn.ModuleList(
|
| 613 |
+
[
|
| 614 |
+
DeepseekV32MLP(config, intermediate_size=config.moe_intermediate_size)
|
| 615 |
+
for _ in range(config.n_routed_experts)
|
| 616 |
+
]
|
| 617 |
+
)
|
| 618 |
+
self.gate = DeepseekV32TopkRouter(config)
|
| 619 |
+
self.shared_experts = DeepseekV32MLP(
|
| 620 |
+
config=config, intermediate_size=config.moe_intermediate_size * config.n_shared_experts
|
| 621 |
+
)
|
| 622 |
+
|
| 623 |
+
def moe(self, hidden_states: torch.Tensor, topk_indices: torch.Tensor, topk_weights: torch.Tensor):
|
| 624 |
+
r"""
|
| 625 |
+
CALL FOR CONTRIBUTION! I don't have time to optimise this right now, but expert weights need to be fused
|
| 626 |
+
to not have to do a loop here (deepseek has 256 experts soooo yeah).
|
| 627 |
+
"""
|
| 628 |
+
final_hidden_states = torch.zeros_like(hidden_states, dtype=topk_weights.dtype)
|
| 629 |
+
expert_mask = torch.nn.functional.one_hot(topk_indices, num_classes=len(self.experts))
|
| 630 |
+
expert_mask = expert_mask.permute(2, 0, 1)
|
| 631 |
+
|
| 632 |
+
for expert_idx in range(len(self.experts)):
|
| 633 |
+
expert = self.experts[expert_idx]
|
| 634 |
+
mask = expert_mask[expert_idx]
|
| 635 |
+
token_indices, weight_indices = torch.where(mask)
|
| 636 |
+
|
| 637 |
+
if token_indices.numel() > 0:
|
| 638 |
+
expert_weights = topk_weights[token_indices, weight_indices]
|
| 639 |
+
expert_input = hidden_states[token_indices]
|
| 640 |
+
expert_output = expert(expert_input)
|
| 641 |
+
weighted_output = expert_output * expert_weights.unsqueeze(-1)
|
| 642 |
+
final_hidden_states.index_add_(0, token_indices, weighted_output)
|
| 643 |
+
|
| 644 |
+
# in original deepseek, the output of the experts are gathered once we leave this module
|
| 645 |
+
# thus the moe module is itelsf an IsolatedParallel module
|
| 646 |
+
# and all expert are "local" meaning we shard but we don't gather
|
| 647 |
+
return final_hidden_states.type(hidden_states.dtype)
|
| 648 |
+
|
| 649 |
+
def forward(self, hidden_states):
|
| 650 |
+
residuals = hidden_states
|
| 651 |
+
orig_shape = hidden_states.shape
|
| 652 |
+
topk_indices, topk_weights = self.gate(hidden_states)
|
| 653 |
+
hidden_states = hidden_states.view(-1, hidden_states.shape[-1])
|
| 654 |
+
hidden_states = self.moe(hidden_states, topk_indices, topk_weights).view(*orig_shape)
|
| 655 |
+
hidden_states = hidden_states + self.shared_experts(residuals)
|
| 656 |
+
return hidden_states
|
| 657 |
+
|
| 658 |
+
|
| 659 |
+
|
| 660 |
+
class DeepseekV32DecoderLayer(GradientCheckpointingLayer):
|
| 661 |
+
def __init__(self, config: DeepseekV32Config, layer_idx: int):
|
| 662 |
+
super().__init__()
|
| 663 |
+
self.hidden_size = config.hidden_size
|
| 664 |
+
self.self_attn = DeepseekV32Attention(config, layer_idx)
|
| 665 |
+
|
| 666 |
+
if config.mlp_layer_types[layer_idx] == "sparse":
|
| 667 |
+
self.mlp = DeepseekV32MoE(config)
|
| 668 |
+
else:
|
| 669 |
+
self.mlp = DeepseekV32MLP(config)
|
| 670 |
+
|
| 671 |
+
self.input_layernorm = DeepseekV32RMSNorm(config.hidden_size, config.rms_norm_eps)
|
| 672 |
+
self.post_attention_layernorm = DeepseekV32RMSNorm(config.hidden_size, config.rms_norm_eps)
|
| 673 |
+
|
| 674 |
+
def forward(
|
| 675 |
+
self,
|
| 676 |
+
hidden_states: torch.Tensor,
|
| 677 |
+
attention_mask: torch.Tensor | None = None,
|
| 678 |
+
position_ids: torch.LongTensor | None = None,
|
| 679 |
+
past_key_values: Cache | None = None,
|
| 680 |
+
use_cache: bool | None = False,
|
| 681 |
+
cache_position: torch.LongTensor | None = None,
|
| 682 |
+
position_embeddings: tuple[torch.Tensor, torch.Tensor] | None = None,
|
| 683 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 684 |
+
) -> torch.Tensor:
|
| 685 |
+
residual = hidden_states
|
| 686 |
+
hidden_states = self.input_layernorm(hidden_states)
|
| 687 |
+
# Self Attention
|
| 688 |
+
hidden_states, _ = self.self_attn(
|
| 689 |
+
hidden_states=hidden_states,
|
| 690 |
+
attention_mask=attention_mask,
|
| 691 |
+
position_ids=position_ids,
|
| 692 |
+
past_key_values=past_key_values,
|
| 693 |
+
use_cache=use_cache,
|
| 694 |
+
cache_position=cache_position,
|
| 695 |
+
position_embeddings=position_embeddings,
|
| 696 |
+
**kwargs,
|
| 697 |
+
)
|
| 698 |
+
hidden_states = residual + hidden_states
|
| 699 |
+
|
| 700 |
+
# Fully Connected
|
| 701 |
+
residual = hidden_states
|
| 702 |
+
hidden_states = self.post_attention_layernorm(hidden_states)
|
| 703 |
+
hidden_states = self.mlp(hidden_states)
|
| 704 |
+
hidden_states = residual + hidden_states
|
| 705 |
+
return hidden_states
|
| 706 |
+
|
| 707 |
+
|
| 708 |
+
class DeepseekV32PreTrainedModel(PreTrainedModel):
|
| 709 |
+
config: DeepseekV32Config
|
| 710 |
+
base_model_prefix = "model"
|
| 711 |
+
supports_gradient_checkpointing = True
|
| 712 |
+
_no_split_modules = ["DeepseekV32DecoderLayer"]
|
| 713 |
+
_skip_keys_device_placement = ["past_key_values"]
|
| 714 |
+
_supports_flash_attn = True
|
| 715 |
+
_supports_sdpa = True
|
| 716 |
+
_supports_flex_attn = True
|
| 717 |
+
_can_compile_fullgraph = False
|
| 718 |
+
_supports_attention_backend = True
|
| 719 |
+
_can_record_outputs = {
|
| 720 |
+
"hidden_states":DeepseekV32DecoderLayer,
|
| 721 |
+
"attentions": DeepseekV32Attention,
|
| 722 |
+
}
|
| 723 |
+
|
| 724 |
+
@torch.no_grad()
|
| 725 |
+
def _init_weights(self, module):
|
| 726 |
+
super()._init_weights(module)
|
| 727 |
+
if isinstance(module, DeepseekV32TopkRouter):
|
| 728 |
+
module.weight.data.normal_(mean=0.0, std=self.config.initializer_range)
|
| 729 |
+
|
| 730 |
+
|
| 731 |
+
class DeepseekV32RotaryEmbedding(nn.Module):
|
| 732 |
+
inv_freq: torch.Tensor # fix linting for `register_buffer`
|
| 733 |
+
|
| 734 |
+
def __init__(self, config: DeepseekV32Config, device=None):
|
| 735 |
+
super().__init__()
|
| 736 |
+
self.max_seq_len_cached = config.max_position_embeddings
|
| 737 |
+
self.original_max_seq_len = config.max_position_embeddings
|
| 738 |
+
|
| 739 |
+
self.config = config
|
| 740 |
+
|
| 741 |
+
self.rope_type = self.config.rope_scaling["rope_type"]
|
| 742 |
+
rope_init_fn: Callable = self.compute_default_rope_parameters
|
| 743 |
+
if self.rope_type != "default":
|
| 744 |
+
rope_init_fn = ROPE_INIT_FUNCTIONS[self.rope_type]
|
| 745 |
+
inv_freq, self.attention_scaling = rope_init_fn(self.config, device)
|
| 746 |
+
|
| 747 |
+
self.register_buffer("inv_freq", inv_freq, persistent=False)
|
| 748 |
+
self.register_buffer("original_inv_freq", inv_freq.clone(), persistent=False)
|
| 749 |
+
|
| 750 |
+
@staticmethod
|
| 751 |
+
def compute_default_rope_parameters(
|
| 752 |
+
config: DeepseekV32Config | None = None,
|
| 753 |
+
device: Optional["torch.device"] = None,
|
| 754 |
+
seq_len: int | None = None,
|
| 755 |
+
) -> tuple["torch.Tensor", float]:
|
| 756 |
+
"""
|
| 757 |
+
Computes the inverse frequencies according to the original RoPE implementation
|
| 758 |
+
Args:
|
| 759 |
+
config ([`~transformers.PreTrainedConfig`]):
|
| 760 |
+
The model configuration.
|
| 761 |
+
device (`torch.device`):
|
| 762 |
+
The device to use for initialization of the inverse frequencies.
|
| 763 |
+
seq_len (`int`, *optional*):
|
| 764 |
+
The current sequence length. Unused for this type of RoPE.
|
| 765 |
+
Returns:
|
| 766 |
+
Tuple of (`torch.Tensor`, `float`), containing the inverse frequencies for the RoPE embeddings and the
|
| 767 |
+
post-processing scaling factor applied to the computed cos/sin (unused in this type of RoPE).
|
| 768 |
+
"""
|
| 769 |
+
base = config.rope_theta
|
| 770 |
+
partial_rotary_factor = config.rope_scaling.get("partial_rotary_factor", 1.0)
|
| 771 |
+
head_dim = getattr(config, "head_dim", None) or config.hidden_size // config.num_attention_heads
|
| 772 |
+
dim = int(head_dim * partial_rotary_factor)
|
| 773 |
+
|
| 774 |
+
attention_factor = 1.0 # Unused in this type of RoPE
|
| 775 |
+
|
| 776 |
+
# Compute the inverse frequencies
|
| 777 |
+
inv_freq = 1.0 / (
|
| 778 |
+
base ** (torch.arange(0, dim, 2, dtype=torch.int64).to(device=device, dtype=torch.float) / dim)
|
| 779 |
+
)
|
| 780 |
+
return inv_freq, attention_factor
|
| 781 |
+
|
| 782 |
+
@torch.no_grad()
|
| 783 |
+
@dynamic_rope_update # power user: used with advanced RoPE types (e.g. dynamic rope)
|
| 784 |
+
def forward(self, x, position_ids):
|
| 785 |
+
inv_freq_expanded = self.inv_freq[None, :, None].float().expand(position_ids.shape[0], -1, 1).to(x.device)
|
| 786 |
+
position_ids_expanded = position_ids[:, None, :].float()
|
| 787 |
+
|
| 788 |
+
device_type = x.device.type if isinstance(x.device.type, str) and x.device.type != "mps" else "cpu"
|
| 789 |
+
with torch.autocast(device_type=device_type, enabled=False): # Force float32
|
| 790 |
+
freqs = (inv_freq_expanded.float() @ position_ids_expanded.float()).transpose(1, 2)
|
| 791 |
+
emb = torch.cat((freqs, freqs), dim=-1)
|
| 792 |
+
cos = emb.cos() * self.attention_scaling
|
| 793 |
+
sin = emb.sin() * self.attention_scaling
|
| 794 |
+
|
| 795 |
+
return cos.to(dtype=x.dtype), sin.to(dtype=x.dtype)
|
| 796 |
+
|
| 797 |
+
|
| 798 |
+
class DeepseekV32Model(DeepseekV32PreTrainedModel):
|
| 799 |
+
_keys_to_ignore_on_load_unexpected = [r"model\.layers\.78.*"]
|
| 800 |
+
|
| 801 |
+
def __init__(self, config: DeepseekV32Config):
|
| 802 |
+
super().__init__(config)
|
| 803 |
+
self.padding_idx = config.pad_token_id
|
| 804 |
+
self.vocab_size = config.vocab_size
|
| 805 |
+
|
| 806 |
+
self.embed_tokens = nn.Embedding(config.vocab_size, config.hidden_size, self.padding_idx)
|
| 807 |
+
self.layers = nn.ModuleList(
|
| 808 |
+
[DeepseekV32DecoderLayer(config, layer_idx) for layer_idx in range(config.num_hidden_layers)]
|
| 809 |
+
)
|
| 810 |
+
self.norm = DeepseekV32RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 811 |
+
self.rotary_emb = DeepseekV32RotaryEmbedding(config=config)
|
| 812 |
+
self.gradient_checkpointing = False
|
| 813 |
+
|
| 814 |
+
# Initialize weights and apply final processing
|
| 815 |
+
self.post_init()
|
| 816 |
+
|
| 817 |
+
@check_model_inputs
|
| 818 |
+
def forward(
|
| 819 |
+
self,
|
| 820 |
+
input_ids: torch.LongTensor | None = None,
|
| 821 |
+
attention_mask: torch.Tensor | None = None,
|
| 822 |
+
position_ids: torch.LongTensor | None = None,
|
| 823 |
+
past_key_values: Cache | None = None,
|
| 824 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 825 |
+
cache_position: torch.LongTensor | None = None,
|
| 826 |
+
use_cache: bool | None = None,
|
| 827 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 828 |
+
) -> BaseModelOutputWithPast:
|
| 829 |
+
if (input_ids is None) ^ (inputs_embeds is not None):
|
| 830 |
+
raise ValueError("You must specify exactly one of input_ids or inputs_embeds")
|
| 831 |
+
|
| 832 |
+
if inputs_embeds is None:
|
| 833 |
+
inputs_embeds: torch.Tensor = self.embed_tokens(input_ids)
|
| 834 |
+
|
| 835 |
+
if use_cache and past_key_values is None:
|
| 836 |
+
past_key_values = DynamicCache(config=self.config)
|
| 837 |
+
|
| 838 |
+
if cache_position is None:
|
| 839 |
+
past_seen_tokens = past_key_values.get_seq_length() if past_key_values is not None else 0
|
| 840 |
+
cache_position: torch.Tensor = (
|
| 841 |
+
torch.arange(inputs_embeds.shape[1], device=inputs_embeds.device) + past_seen_tokens
|
| 842 |
+
)
|
| 843 |
+
|
| 844 |
+
if position_ids is None:
|
| 845 |
+
position_ids = cache_position.unsqueeze(0)
|
| 846 |
+
|
| 847 |
+
causal_mask = create_causal_mask(
|
| 848 |
+
config=self.config,
|
| 849 |
+
input_embeds=inputs_embeds,
|
| 850 |
+
attention_mask=attention_mask,
|
| 851 |
+
cache_position=cache_position,
|
| 852 |
+
past_key_values=past_key_values,
|
| 853 |
+
position_ids=position_ids,
|
| 854 |
+
)
|
| 855 |
+
|
| 856 |
+
hidden_states = inputs_embeds
|
| 857 |
+
position_embeddings = self.rotary_emb(hidden_states, position_ids=position_ids)
|
| 858 |
+
|
| 859 |
+
for decoder_layer in self.layers[: self.config.num_hidden_layers]:
|
| 860 |
+
hidden_states = decoder_layer(
|
| 861 |
+
hidden_states,
|
| 862 |
+
attention_mask=causal_mask,
|
| 863 |
+
position_embeddings=position_embeddings,
|
| 864 |
+
position_ids=position_ids,
|
| 865 |
+
past_key_values=past_key_values,
|
| 866 |
+
use_cache=use_cache,
|
| 867 |
+
cache_position=cache_position,
|
| 868 |
+
**kwargs,
|
| 869 |
+
)
|
| 870 |
+
|
| 871 |
+
hidden_states = self.norm(hidden_states)
|
| 872 |
+
return BaseModelOutputWithPast(
|
| 873 |
+
last_hidden_state=hidden_states,
|
| 874 |
+
past_key_values=past_key_values,
|
| 875 |
+
)
|
| 876 |
+
|
| 877 |
+
|
| 878 |
+
class DeepseekV32ForCausalLM(DeepseekV32PreTrainedModel, GenerationMixin):
|
| 879 |
+
_tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}
|
| 880 |
+
_tp_plan = {"lm_head": "colwise_gather_output"}
|
| 881 |
+
_pp_plan = {"lm_head": (["hidden_states"], ["logits"])}
|
| 882 |
+
|
| 883 |
+
def __init__(self, config):
|
| 884 |
+
super().__init__(config)
|
| 885 |
+
self.model = DeepseekV32Model(config)
|
| 886 |
+
self.vocab_size = config.vocab_size
|
| 887 |
+
self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
|
| 888 |
+
|
| 889 |
+
# Initialize weights and apply final processing
|
| 890 |
+
self.post_init()
|
| 891 |
+
|
| 892 |
+
@can_return_tuple
|
| 893 |
+
def forward(
|
| 894 |
+
self,
|
| 895 |
+
input_ids: torch.LongTensor | None = None,
|
| 896 |
+
attention_mask: torch.Tensor | None = None,
|
| 897 |
+
position_ids: torch.LongTensor | None = None,
|
| 898 |
+
past_key_values: Cache | None = None,
|
| 899 |
+
inputs_embeds: torch.FloatTensor | None = None,
|
| 900 |
+
labels: torch.LongTensor | None = None,
|
| 901 |
+
use_cache: bool | None = None,
|
| 902 |
+
cache_position: torch.LongTensor | None = None,
|
| 903 |
+
logits_to_keep: int | torch.Tensor = 0,
|
| 904 |
+
**kwargs: Unpack[TransformersKwargs],
|
| 905 |
+
) -> CausalLMOutputWithPast:
|
| 906 |
+
outputs: BaseModelOutputWithPast = self.model(
|
| 907 |
+
input_ids=input_ids,
|
| 908 |
+
attention_mask=attention_mask,
|
| 909 |
+
position_ids=position_ids,
|
| 910 |
+
past_key_values=past_key_values,
|
| 911 |
+
inputs_embeds=inputs_embeds,
|
| 912 |
+
use_cache=use_cache,
|
| 913 |
+
cache_position=cache_position,
|
| 914 |
+
**kwargs,
|
| 915 |
+
)
|
| 916 |
+
|
| 917 |
+
hidden_states = outputs.last_hidden_state
|
| 918 |
+
# Only compute necessary logits, and do not upcast them to float if we are not computing the loss
|
| 919 |
+
slice_indices = slice(-logits_to_keep, None) if isinstance(logits_to_keep, int) else logits_to_keep
|
| 920 |
+
logits = self.lm_head(hidden_states[:, slice_indices, :])
|
| 921 |
+
|
| 922 |
+
loss = None
|
| 923 |
+
if labels is not None:
|
| 924 |
+
loss = self.loss_function(logits=logits, labels=labels, vocab_size=self.config.vocab_size, **kwargs)
|
| 925 |
+
|
| 926 |
+
return CausalLMOutputWithPast(
|
| 927 |
+
loss=loss,
|
| 928 |
+
logits=logits,
|
| 929 |
+
past_key_values=outputs.past_key_values,
|
| 930 |
+
hidden_states=outputs.hidden_states,
|
| 931 |
+
attentions=outputs.attentions,
|
| 932 |
+
)
|
| 933 |
+
|
| 934 |
+
|
| 935 |
+
__all__ = ["DeepseekV32PreTrainedModel", "DeepseekV32Model", "DeepseekV32ForCausalLM"]
|
tokenizer.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"add_bos_token": false,
|
| 3 |
+
"add_eos_token": false,
|
| 4 |
+
"bos_token": {
|
| 5 |
+
"__type": "AddedToken",
|
| 6 |
+
"content": "<|begin▁of▁sentence|>",
|
| 7 |
+
"lstrip": false,
|
| 8 |
+
"normalized": true,
|
| 9 |
+
"rstrip": false,
|
| 10 |
+
"single_word": false
|
| 11 |
+
},
|
| 12 |
+
"clean_up_tokenization_spaces": false,
|
| 13 |
+
"eos_token": {
|
| 14 |
+
"__type": "AddedToken",
|
| 15 |
+
"content": "<|end▁of▁sentence|>",
|
| 16 |
+
"lstrip": false,
|
| 17 |
+
"normalized": true,
|
| 18 |
+
"rstrip": false,
|
| 19 |
+
"single_word": false
|
| 20 |
+
},
|
| 21 |
+
"legacy": true,
|
| 22 |
+
"model_max_length": 131072,
|
| 23 |
+
"pad_token": {
|
| 24 |
+
"__type": "AddedToken",
|
| 25 |
+
"content": "<|end▁of▁sentence|>",
|
| 26 |
+
"lstrip": false,
|
| 27 |
+
"normalized": true,
|
| 28 |
+
"rstrip": false,
|
| 29 |
+
"single_word": false
|
| 30 |
+
},
|
| 31 |
+
"sp_model_kwargs": {},
|
| 32 |
+
"unk_token": null,
|
| 33 |
+
"tokenizer_class": "LlamaTokenizerFast"
|
| 34 |
+
}
|