add time series safetensors

#4
by yehaochen - opened
0092638_seism.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c2b94653c6964b630038897a27cb6d276ff866d9ecd1f6419358b9407f0df62e
3
+ size 72128
README.md CHANGED
@@ -290,7 +290,7 @@ print(json.dumps(response.model_dump(), indent=2, ensure_ascii=False))
290
  Time series inference is currently only supported in LMDeploy. To get started, download and deploy Intern-S2-Preview-397B with LMDeploy by following the [Model Deployment Guide](./deployment_guide.md).
291
  Below is an example of detecting earthquake events from a time series signal file. Additional data types and functionalities are also supported.
292
 
293
- **Please note**: this demo is slightly different from the one in [Intern-S1-Pro](https://huggingface.co/internlm/Intern-S1-Pro#time-series-demo). The main difference is that in the messages content, you need to provide time_series_url first, followed by the text prompt. Please adapt your implementation based on this demo.
294
 
295
  ```
296
  from openai import OpenAI
@@ -413,6 +413,57 @@ print(response.choices[0].message)
413
 
414
  ```
415
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
  ## Agent Integration
417
 
418
  Intern-S2-Preview-397B can be plugged into agent frameworks in two ways: connecting to a **self-hosted deployment**, or calling the **official InternLM API**. Below we cover both, with examples for agent frameworks (OpenClaw, Hermes, etc.) and for Claude Code.
 
290
  Time series inference is currently only supported in LMDeploy. To get started, download and deploy Intern-S2-Preview-397B with LMDeploy by following the [Model Deployment Guide](./deployment_guide.md).
291
  Below is an example of detecting earthquake events from a time series signal file. Additional data types and functionalities are also supported.
292
 
293
+ **Please note**: in the message content, the order of time_series_url and the text prompt can be arbitrary.
294
 
295
  ```
296
  from openai import OpenAI
 
413
 
414
  ```
415
 
416
+ For time series forecasting, `forecast_horizon` is optional. Set it to an integer to produce a forecast of exactly that length, or set it to `None` to let the model infer the horizon from the text prompt.
417
+
418
+ ```
419
+ def forecast_base64(file_path: str, forecast_horizon: int | None = None):
420
+ base64_ts = encode_time_series_base64(file_path)
421
+ messages = [
422
+ {
423
+ "role": "user",
424
+ "content": [
425
+ {
426
+ "type": "text",
427
+ "text": (
428
+ "Please complete a electric load forecasting task. "
429
+ "This dataset is based on historical electricity load data every half hour within 24 hours of the region, "
430
+ "as well as data on minimum temperature, maximum temperature, humidity, air pressure, etc., "
431
+ "to predict future load consumption every half hour within 24 hours. Here is the weather information for city TAS: "
432
+ "Historical date weather: minimum temperature of 279.71K, maximum temperature of 285.83K, humidity of 85.0%, "
433
+ "air pressure of 1003.0hPa. Forecast date weather: minimum temperature 280.54K, maximum temperature 286.47K, "
434
+ "humidity 74.0%, air pressure 1007.0hPa. This data has no relevant effect information. "
435
+ "Please predict the next 48 time points given information above."
436
+ ),
437
+ },
438
+ {
439
+ "type": "time_series_url",
440
+ "time_series_url": {
441
+ "url": f"data:time_series/npy;base64,{base64_ts}",
442
+ },
443
+ },
444
+ ],
445
+ }
446
+ ]
447
+
448
+ return client.chat.completions.create(
449
+ model=model_name,
450
+ messages=messages,
451
+ temperature=0,
452
+ max_tokens=16,
453
+ extra_body={
454
+ "chat_template_kwargs": {"enable_thinking": False},
455
+ "enable_forecasting": True,
456
+ "forecast_horizon": forecast_horizon,
457
+ },
458
+ )
459
+
460
+
461
+ response = forecast_base64("./load_20210803_0.npy", forecast_horizon=None)
462
+ forecast = response.choices[0].message.ts_forecast
463
+ print("Point forecast:", forecast.point_forecast)
464
+ print("Quantile forecast:", forecast.quantile_forecast)
465
+ ```
466
+
467
  ## Agent Integration
468
 
469
  Intern-S2-Preview-397B can be plugged into agent frameworks in two ways: connecting to a **self-hosted deployment**, or calling the **official InternLM API**. Below we cover both, with examples for agent frameworks (OpenClaw, Hermes, etc.) and for Claude Code.
chat_template.jinja CHANGED
@@ -27,6 +27,11 @@
27
  {{- 'Video ' ~ video_count.value ~ ': ' }}
28
  {%- endif %}
29
  {{- '<|vision_start|><|video_pad|><|vision_end|>' }}
 
 
 
 
 
30
  {%- elif 'text' in item %}
31
  {{- item.text }}
32
  {%- else %}
@@ -42,6 +47,16 @@
42
  {%- if not messages %}
43
  {{- raise_exception('No messages provided.') }}
44
  {%- endif %}
 
 
 
 
 
 
 
 
 
 
45
  {%- if tools and tools is iterable and tools is not mapping %}
46
  {{- '<|im_start|>system\n' }}
47
  {{- "# Tools\n\nYou have access to the following functions:\n\n<tools>" }}
@@ -139,7 +154,7 @@
139
  {%- endfor %}
140
  {%- if add_generation_prompt %}
141
  {{- '<|im_start|>assistant\n' }}
142
- {%- if enable_thinking is defined and enable_thinking is false %}
143
  {{- '<think>\n\n</think>\n\n' }}
144
  {%- else %}
145
  {{- '<think>\n' }}
 
27
  {{- 'Video ' ~ video_count.value ~ ': ' }}
28
  {%- endif %}
29
  {{- '<|vision_start|><|video_pad|><|vision_end|>' }}
30
+ {%- elif 'time_series' in item or item.type == 'time_series' %}
31
+ {%- if is_system_content %}
32
+ {{- raise_exception('System message cannot contain time series.') }}
33
+ {%- endif %}
34
+ {{- '<|ts|><TS_CONTEXT><|/ts|>' }}
35
  {%- elif 'text' in item %}
36
  {{- item.text }}
37
  {%- else %}
 
47
  {%- if not messages %}
48
  {{- raise_exception('No messages provided.') }}
49
  {%- endif %}
50
+ {%- set ts_ns = namespace(has_time_series=false) %}
51
+ {%- for message in messages %}
52
+ {%- if message.content is iterable and message.content is not mapping and message.content is not string %}
53
+ {%- for item in message.content %}
54
+ {%- if 'time_series' in item or item.type == 'time_series' %}
55
+ {%- set ts_ns.has_time_series = true %}
56
+ {%- endif %}
57
+ {%- endfor %}
58
+ {%- endif %}
59
+ {%- endfor %}
60
  {%- if tools and tools is iterable and tools is not mapping %}
61
  {{- '<|im_start|>system\n' }}
62
  {{- "# Tools\n\nYou have access to the following functions:\n\n<tools>" }}
 
154
  {%- endfor %}
155
  {%- if add_generation_prompt %}
156
  {{- '<|im_start|>assistant\n' }}
157
+ {%- if ts_ns.has_time_series or (enable_thinking is defined and enable_thinking is false) %}
158
  {{- '<think>\n\n</think>\n\n' }}
159
  {%- else %}
160
  {{- '<think>\n' }}
config.json CHANGED
@@ -161,13 +161,43 @@
161
  "encoder_layers": 17,
162
  "max_source_positions": 1500,
163
  "num_mel_bins": 80,
164
- "out_hidden_size": 2048,
165
  "scale_embedding": false,
166
  "ts_adapt_in_dim": 256,
167
  "ts_adapt_out_dim": 1024,
168
- "ts_hidden_dim": 1024
 
 
 
 
 
 
 
 
169
  },
170
  "ts_token_id": 248093,
171
  "ts_start_id": 248091,
172
- "ts_end_id": 248092
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  }
 
161
  "encoder_layers": 17,
162
  "max_source_positions": 1500,
163
  "num_mel_bins": 80,
164
+ "out_hidden_size": 4096,
165
  "scale_embedding": false,
166
  "ts_adapt_in_dim": 256,
167
  "ts_adapt_out_dim": 1024,
168
+ "ts_hidden_dim": 1024,
169
+ "chunk_size": 12800,
170
+ "chunk_step": 12800,
171
+ "subsampling_hidden_dim": 128,
172
+ "subsampling_nhead": 8,
173
+ "subsampling_patch": 50,
174
+ "subsampling_num_query": 2,
175
+ "subsampling_num_conv_layers": 0,
176
+ "subsampling_selfatt": false
177
  },
178
  "ts_token_id": 248093,
179
  "ts_start_id": 248091,
180
+ "ts_end_id": 248092,
181
+ "ts_forecaster_config": {
182
+ "model_type": "interns2_preview_time_series_forecaster",
183
+ "d_llm": 4096,
184
+ "d_ts_encoder": 1024,
185
+ "qformer_hidden_dim": 1280,
186
+ "qformer_num_query_tokens": 16,
187
+ "qformer_num_heads": 8,
188
+ "qformer_num_layers": 2,
189
+ "qformer_dropout": 0.0,
190
+ "use_horizon_head": true,
191
+ "horizon_max_length": 0,
192
+ "use_cross_attn_gate": true,
193
+ "max_context": 2048,
194
+ "max_horizon": 1024,
195
+ "normalize_inputs": true,
196
+ "use_continuous_quantile_head": true,
197
+ "force_flip_invariance": true,
198
+ "infer_is_positive": true,
199
+ "fix_quantile_crossing": true,
200
+ "return_backcast": false,
201
+ "default_pred_len": 720
202
+ }
203
  }
configuration_interns2_preview.py CHANGED
@@ -21,6 +21,57 @@ from transformers.configuration_utils import PreTrainedConfig, layer_type_valida
21
  from transformers.modeling_rope_utils import RopeParameters
22
 
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  class InternS2PreviewVisionConfig(PreTrainedConfig):
25
  model_type = "intern_s2_preview"
26
  base_config_key = "vision_config"
@@ -306,6 +357,14 @@ class InternS2PreviewTimeSeriesConfig(PreTrainedConfig):
306
  ts_adapt_in_dim: int = 256,
307
  ts_adapt_out_dim: int = 1024,
308
  ts_hidden_dim: int = 1024,
 
 
 
 
 
 
 
 
309
  **super_kwargs,
310
  ):
311
  super().__init__(**super_kwargs)
@@ -330,10 +389,83 @@ class InternS2PreviewTimeSeriesConfig(PreTrainedConfig):
330
  self.ts_adapt_in_dim = ts_adapt_in_dim
331
  self.ts_adapt_out_dim = ts_adapt_out_dim
332
  self.ts_hidden_dim = ts_hidden_dim
 
 
 
 
 
 
 
 
333
 
334
  assert self.ts_adapt_out_dim == self.ts_hidden_dim, "ts_adapt_out_dim should be equal to ts_hidden_dim"
335
 
336
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337
  class InternS2PreviewConfig(PreTrainedConfig):
338
  r"""
339
  This is the configuration class to store the configuration of a [`InternS2PreviewModel`]. It is used to instantiate a
@@ -379,6 +511,7 @@ class InternS2PreviewConfig(PreTrainedConfig):
379
  "vision_config": InternS2PreviewVisionConfig,
380
  "text_config": InternS2PreviewTextConfig,
381
  "ts_config": InternS2PreviewTimeSeriesConfig,
 
382
  }
383
  keys_to_ignore_at_inference = ["past_key_values"]
384
 
@@ -395,16 +528,9 @@ class InternS2PreviewConfig(PreTrainedConfig):
395
  ts_token_id=248093,
396
  ts_start_id=248091,
397
  ts_end_id=248092,
 
398
  **kwargs,
399
  ):
400
- if isinstance(ts_config, dict):
401
- self.ts_config = self.sub_configs["ts_config"](**ts_config)
402
- elif ts_config is None:
403
- self.ts_config = self.sub_configs["ts_config"]()
404
-
405
- self.ts_token_id = ts_token_id
406
- self.ts_start_id = ts_start_id
407
- self.ts_end_id = ts_end_id
408
  if isinstance(vision_config, dict):
409
  self.vision_config = self.sub_configs["vision_config"](**vision_config)
410
  elif vision_config is None:
@@ -421,6 +547,23 @@ class InternS2PreviewConfig(PreTrainedConfig):
421
  self.vision_end_token_id = vision_end_token_id
422
  self.tie_word_embeddings = tie_word_embeddings
423
  super().__init__(**kwargs)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
  self.auto_map = {
425
  "AutoConfig": "configuration_interns2_preview.InternS2PreviewConfig",
426
  "AutoModelForCausalLM": "modeling_interns2_preview.InternS2PreviewForCausalLM",
 
21
  from transformers.modeling_rope_utils import RopeParameters
22
 
23
 
24
+ class InternS2PreviewBertConfig(PreTrainedConfig):
25
+ model_type = "intern_s2_preview_bert"
26
+
27
+ def __init__(
28
+ self,
29
+ vocab_size=30522,
30
+ hidden_size=768,
31
+ num_hidden_layers=12,
32
+ num_attention_heads=12,
33
+ intermediate_size=3072,
34
+ hidden_act="gelu",
35
+ hidden_dropout_prob=0.1,
36
+ attention_probs_dropout_prob=0.1,
37
+ max_position_embeddings=512,
38
+ type_vocab_size=2,
39
+ initializer_range=0.02,
40
+ layer_norm_eps=1e-12,
41
+ pad_token_id=0,
42
+ use_cache=True,
43
+ classifier_dropout=None,
44
+ is_decoder=False,
45
+ add_cross_attention=False,
46
+ bos_token_id=None,
47
+ eos_token_id=None,
48
+ tie_word_embeddings=True,
49
+ **kwargs,
50
+ ):
51
+ super().__init__(**kwargs)
52
+ self.pad_token_id = pad_token_id
53
+ self.is_decoder = is_decoder
54
+ self.add_cross_attention = add_cross_attention
55
+ self.bos_token_id = bos_token_id
56
+ self.eos_token_id = eos_token_id
57
+ self.tie_word_embeddings = tie_word_embeddings
58
+
59
+ self.vocab_size = vocab_size
60
+ self.hidden_size = hidden_size
61
+ self.num_hidden_layers = num_hidden_layers
62
+ self.num_attention_heads = num_attention_heads
63
+ self.hidden_act = hidden_act
64
+ self.intermediate_size = intermediate_size
65
+ self.hidden_dropout_prob = hidden_dropout_prob
66
+ self.attention_probs_dropout_prob = attention_probs_dropout_prob
67
+ self.max_position_embeddings = max_position_embeddings
68
+ self.type_vocab_size = type_vocab_size
69
+ self.initializer_range = initializer_range
70
+ self.layer_norm_eps = layer_norm_eps
71
+ self.use_cache = use_cache
72
+ self.classifier_dropout = classifier_dropout
73
+
74
+
75
  class InternS2PreviewVisionConfig(PreTrainedConfig):
76
  model_type = "intern_s2_preview"
77
  base_config_key = "vision_config"
 
357
  ts_adapt_in_dim: int = 256,
358
  ts_adapt_out_dim: int = 1024,
359
  ts_hidden_dim: int = 1024,
360
+ chunk_size: int = 12800,
361
+ chunk_step: int = 12800,
362
+ subsampling_hidden_dim: int = 128,
363
+ subsampling_nhead: int = 8,
364
+ subsampling_patch: int = 50,
365
+ subsampling_num_query: int = 2,
366
+ subsampling_num_conv_layers: int = 0,
367
+ subsampling_selfatt: bool = False,
368
  **super_kwargs,
369
  ):
370
  super().__init__(**super_kwargs)
 
389
  self.ts_adapt_in_dim = ts_adapt_in_dim
390
  self.ts_adapt_out_dim = ts_adapt_out_dim
391
  self.ts_hidden_dim = ts_hidden_dim
392
+ self.chunk_size = chunk_size
393
+ self.chunk_step = chunk_step
394
+ self.subsampling_hidden_dim = subsampling_hidden_dim
395
+ self.subsampling_nhead = subsampling_nhead
396
+ self.subsampling_patch = subsampling_patch
397
+ self.subsampling_num_query = subsampling_num_query
398
+ self.subsampling_num_conv_layers = subsampling_num_conv_layers
399
+ self.subsampling_selfatt = subsampling_selfatt
400
 
401
  assert self.ts_adapt_out_dim == self.ts_hidden_dim, "ts_adapt_out_dim should be equal to ts_hidden_dim"
402
 
403
 
404
+ class InternS2PreviewTimeSeriesForecasterConfig(PreTrainedConfig):
405
+ model_type = "interns2_preview_time_series_forecaster"
406
+
407
+ FORECASTER_MODEL_DIMS = 1280
408
+
409
+ def __init__(
410
+ self,
411
+ d_llm: int = 2560,
412
+ d_ts_encoder: int = 1024,
413
+ qformer_hidden_dim: int = 0,
414
+ qformer_num_query_tokens: int = 32,
415
+ qformer_num_heads: int = 8,
416
+ qformer_num_layers: int = 2,
417
+ qformer_dropout: float = 0.0,
418
+ use_horizon_head: bool = True,
419
+ horizon_max_length: int = 0,
420
+ use_cross_attn_gate: bool = True,
421
+ max_context: int = 2048,
422
+ max_horizon: int = 1024,
423
+ normalize_inputs: bool = True,
424
+ use_continuous_quantile_head: bool = True,
425
+ force_flip_invariance: bool = True,
426
+ infer_is_positive: bool = True,
427
+ fix_quantile_crossing: bool = True,
428
+ return_backcast: bool = False,
429
+ default_pred_len: int = 720,
430
+ **super_kwargs,
431
+ ):
432
+ # Precomputed-embedding dims (must match the consumer's LLM / TS encoder).
433
+ self.d_llm = int(d_llm)
434
+ self.d_ts_encoder = int(d_ts_encoder)
435
+
436
+ # Q-former. qformer_hidden_dim == 0 -> default to the Forecaster model dim so
437
+ # the cross-attention KV stream needs no further projection.
438
+ self.qformer_hidden_dim = int(qformer_hidden_dim) or self.FORECASTER_MODEL_DIMS
439
+ self.qformer_num_query_tokens = int(qformer_num_query_tokens)
440
+ self.qformer_num_heads = int(qformer_num_heads)
441
+ self.qformer_num_layers = int(qformer_num_layers)
442
+ self.qformer_dropout = float(qformer_dropout)
443
+
444
+ # Prediction-length head.
445
+ self.use_horizon_head = bool(use_horizon_head)
446
+ self.horizon_max_length = int(horizon_max_length)
447
+
448
+ # Forecaster cross-attention backbone build.
449
+ self.use_cross_attn_gate = bool(use_cross_attn_gate)
450
+ # Cross-attn KV dim equals the compressed-token dim.
451
+ self.cross_attn_kv_dim = self.qformer_hidden_dim
452
+
453
+ # Forecast knobs.
454
+ self.max_context = int(max_context)
455
+ self.max_horizon = int(max_horizon)
456
+ self.normalize_inputs = bool(normalize_inputs)
457
+ self.use_continuous_quantile_head = bool(use_continuous_quantile_head)
458
+ self.force_flip_invariance = bool(force_flip_invariance)
459
+ self.infer_is_positive = bool(infer_is_positive)
460
+ self.fix_quantile_crossing = bool(fix_quantile_crossing)
461
+ self.return_backcast = bool(return_backcast)
462
+
463
+ # Fallback horizon when the horizon head is disabled and no override given.
464
+ self.default_pred_len = int(default_pred_len)
465
+
466
+ super().__init__(**super_kwargs)
467
+
468
+
469
  class InternS2PreviewConfig(PreTrainedConfig):
470
  r"""
471
  This is the configuration class to store the configuration of a [`InternS2PreviewModel`]. It is used to instantiate a
 
511
  "vision_config": InternS2PreviewVisionConfig,
512
  "text_config": InternS2PreviewTextConfig,
513
  "ts_config": InternS2PreviewTimeSeriesConfig,
514
+ "ts_forecaster_config": InternS2PreviewTimeSeriesForecasterConfig,
515
  }
516
  keys_to_ignore_at_inference = ["past_key_values"]
517
 
 
528
  ts_token_id=248093,
529
  ts_start_id=248091,
530
  ts_end_id=248092,
531
+ ts_forecaster_config=None,
532
  **kwargs,
533
  ):
 
 
 
 
 
 
 
 
534
  if isinstance(vision_config, dict):
535
  self.vision_config = self.sub_configs["vision_config"](**vision_config)
536
  elif vision_config is None:
 
547
  self.vision_end_token_id = vision_end_token_id
548
  self.tie_word_embeddings = tie_word_embeddings
549
  super().__init__(**kwargs)
550
+ if isinstance(ts_config, dict):
551
+ self.ts_config = self.sub_configs["ts_config"](**ts_config)
552
+ elif ts_config is None:
553
+ self.ts_config = self.sub_configs["ts_config"]()
554
+
555
+ if isinstance(ts_forecaster_config, dict):
556
+ self.ts_forecaster_config = self.sub_configs["ts_forecaster_config"](**ts_forecaster_config)
557
+ elif ts_forecaster_config is None:
558
+ self.ts_forecaster_config = self.sub_configs["ts_forecaster_config"](
559
+ d_llm=self.text_config.hidden_size,
560
+ d_ts_encoder=self.ts_config.out_hidden_size,
561
+ )
562
+
563
+ self.ts_token_id = ts_token_id
564
+ self.ts_start_id = ts_start_id
565
+ self.ts_end_id = ts_end_id
566
+
567
  self.auto_map = {
568
  "AutoConfig": "configuration_interns2_preview.InternS2PreviewConfig",
569
  "AutoModelForCausalLM": "modeling_interns2_preview.InternS2PreviewForCausalLM",
load_20210803_0.npy ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9c9b6e38aca67dd36a4ba2d31d984549b0ae3a5aa72c545ef2c6662088cb6aae
3
+ size 512
model-time-series-0001.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b82eadda0ac7fd8fedd1a013dd3ee577c3a02cce3426e94af0bb5ec5940da9e9
3
+ size 295550856
model-time-series-0002.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5debb9ec91f1b657fdb66361c8d054c6733c85bd2b1213c1c4a72fe95e4c7177
3
+ size 102400128
model-time-series-0003.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f4fc8d385717a6a3f1a92cae8877c74d381a79014bbd3c998ab88130ea505fd3
3
+ size 1001137994
model.safetensors.index.json CHANGED
The diff for this file is too large to render. See raw diff
 
modeling_interns2_preview.py CHANGED
The diff for this file is too large to render. See raw diff
 
processing_interns2_preview.py CHANGED
@@ -21,6 +21,7 @@ import importlib
21
  import os
22
 
23
  import numpy as np
 
24
 
25
  from transformers.feature_extraction_utils import BatchFeature
26
  from transformers.image_utils import ImageInput
@@ -47,7 +48,42 @@ class InternS2PreviewProcessorKwargs(ProcessingKwargs, total=False):
47
 
48
  @auto_docstring
49
  class InternS2PreviewProcessor(ProcessorMixin):
50
- def __init__(self, image_processor=None, tokenizer=None, video_processor=None, chat_template=None, **kwargs):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  self.image_token = "<|image_pad|>" if not hasattr(tokenizer, "image_token") else tokenizer.image_token
52
  self.video_token = "<|video_pad|>" if not hasattr(tokenizer, "video_token") else tokenizer.video_token
53
  self.image_token_id = (
@@ -95,6 +131,11 @@ class InternS2PreviewProcessor(ProcessorMixin):
95
  if getattr(tokenizer, "ts_token_id", None)
96
  else tokenizer.convert_tokens_to_ids(self.ts_token)
97
  )
 
 
 
 
 
98
 
99
  @auto_docstring
100
  def __call__(
@@ -107,6 +148,18 @@ class InternS2PreviewProcessor(ProcessorMixin):
107
  **kwargs: Unpack[InternS2PreviewProcessorKwargs],
108
  ) -> BatchFeature:
109
  r"""
 
 
 
 
 
 
 
 
 
 
 
 
110
  Returns:
111
  [`BatchFeature`]: A [`BatchFeature`] with the following fields:
112
 
@@ -160,7 +213,10 @@ class InternS2PreviewProcessor(ProcessorMixin):
160
  "The number of time series signals must match the number of sampling rates."
161
  )
162
  time_series_inputs = self.time_series_processor(
163
- ts_paths=time_series_paths, sampling_rates=time_series_sampling_rates
 
 
 
164
  )
165
  num_ts_tokens = time_series_inputs.pop("num_ts_tokens")
166
  assert len(num_ts_tokens) == len(text), (
@@ -368,6 +424,7 @@ class InternS2PreviewProcessor(ProcessorMixin):
368
  ts_values = []
369
  ts_sr = []
370
  ts_lens = []
 
371
 
372
  for idx, ts_path in enumerate(ts_paths):
373
  sr = sampling_rates[idx]
@@ -397,6 +454,7 @@ class InternS2PreviewProcessor(ProcessorMixin):
397
  ts_input = ts_input[:, None] # [T,C]
398
 
399
  ts_len = ts_input.shape[0]
 
400
 
401
  if sr is None or sr == 0: # if no sr provided
402
  sr = ts_len / 4
@@ -404,19 +462,38 @@ class InternS2PreviewProcessor(ProcessorMixin):
404
  ts_values.append(ts_input)
405
  ts_sr.append(sr)
406
  ts_lens.append(ts_len)
 
407
 
 
408
  ts_lens = np.array(ts_lens)
409
  ts_sr = np.array(ts_sr)
410
  num_ts_tokens = self._get_num_ts_tokens(sampling_rates=ts_sr, ts_lens=ts_lens)
411
  return BatchFeature(
412
- data={"ts_values": ts_values, "ts_sr": ts_sr, "ts_lens": ts_lens, "num_ts_tokens": num_ts_tokens}
 
 
 
 
 
 
413
  )
414
 
415
  def _get_num_ts_tokens(self, sampling_rates, ts_lens):
416
- strides = np.floor(160 / ((1 + np.exp(-sampling_rates / 100)) ** 6))
417
- patch_sizes = strides * 2
418
- embed_lengths = (np.ceil((ts_lens - patch_sizes) / strides) + 1).astype(np.int64)
419
- num_ts_tokens = [(embed_length // 2 + 1) // 2 for embed_length in embed_lengths]
 
 
 
 
 
 
 
 
 
 
 
420
  return num_ts_tokens
421
 
422
 
 
21
  import os
22
 
23
  import numpy as np
24
+ import torch
25
 
26
  from transformers.feature_extraction_utils import BatchFeature
27
  from transformers.image_utils import ImageInput
 
48
 
49
  @auto_docstring
50
  class InternS2PreviewProcessor(ProcessorMixin):
51
+ def __init__(
52
+ self,
53
+ image_processor=None,
54
+ tokenizer=None,
55
+ video_processor=None,
56
+ chat_template=None,
57
+ chunk_size=12800,
58
+ patch=50,
59
+ num_query=2,
60
+ ts_signals_do_normalize=True,
61
+ ts_signals_do_truncate=True,
62
+ **kwargs,
63
+ ):
64
+ """
65
+ Constructs an InternS2Preview processor.
66
+
67
+ Args:
68
+ image_processor (`ImageProcessingMixin`, *optional*):
69
+ The image processor.
70
+ tokenizer (`PreTrainedTokenizerBase`, *optional*):
71
+ The tokenizer.
72
+ video_processor (`BaseVideoProcessor`, *optional*):
73
+ The video processor.
74
+ chat_template (`str`, *optional*):
75
+ The chat template used to format conversations.
76
+ chunk_size (`int`, *optional*, defaults to 12800):
77
+ Chunk size used by the time-series encoder.
78
+ patch (`int`, *optional*, defaults to 50):
79
+ Patch size used by the time-series encoder.
80
+ num_query (`int`, *optional*, defaults to 2):
81
+ Number of query tokens used by the time-series encoder.
82
+ ts_signals_do_normalize (`bool`, *optional*, defaults to `True`):
83
+ Whether to normalize each input time-series signal before it is passed to the time-series encoder and/or forecaster.
84
+ ts_signals_do_truncate (`bool`, *optional*, defaults to `True`):
85
+ Whether to truncate input time-series signals that exceed the processor's maximum supported length.
86
+ """
87
  self.image_token = "<|image_pad|>" if not hasattr(tokenizer, "image_token") else tokenizer.image_token
88
  self.video_token = "<|video_pad|>" if not hasattr(tokenizer, "video_token") else tokenizer.video_token
89
  self.image_token_id = (
 
131
  if getattr(tokenizer, "ts_token_id", None)
132
  else tokenizer.convert_tokens_to_ids(self.ts_token)
133
  )
134
+ self.chunk_size = chunk_size
135
+ self.patch = patch
136
+ self.num_query = num_query
137
+ self.ts_signals_do_normalize = ts_signals_do_normalize
138
+ self.ts_signals_do_truncate = ts_signals_do_truncate
139
 
140
  @auto_docstring
141
  def __call__(
 
148
  **kwargs: Unpack[InternS2PreviewProcessorKwargs],
149
  ) -> BatchFeature:
150
  r"""
151
+ Args:
152
+ images (`ImageInput`, *optional*):
153
+ Images to be processed.
154
+ text (`TextInput`, `PreTokenizedInput`, `list[TextInput]`, or `list[PreTokenizedInput]`, *optional*):
155
+ Text to be encoded.
156
+ videos (`VideoInput`, *optional*):
157
+ Videos to be processed.
158
+ time_series_paths (`list[str]`, *optional*):
159
+ Paths to time series files. Supported formats include `.wav`, `.mp3`, `.flac`, `.csv`, and `.npy`.
160
+ time_series_sampling_rates (`list[int]`, *optional*):
161
+ Sampling rates corresponding to `time_series_paths`.
162
+
163
  Returns:
164
  [`BatchFeature`]: A [`BatchFeature`] with the following fields:
165
 
 
213
  "The number of time series signals must match the number of sampling rates."
214
  )
215
  time_series_inputs = self.time_series_processor(
216
+ ts_paths=time_series_paths,
217
+ sampling_rates=time_series_sampling_rates,
218
+ do_normalize=self.ts_signals_do_normalize,
219
+ do_truncate=self.ts_signals_do_truncate,
220
  )
221
  num_ts_tokens = time_series_inputs.pop("num_ts_tokens")
222
  assert len(num_ts_tokens) == len(text), (
 
424
  ts_values = []
425
  ts_sr = []
426
  ts_lens = []
427
+ ts_channels = []
428
 
429
  for idx, ts_path in enumerate(ts_paths):
430
  sr = sampling_rates[idx]
 
454
  ts_input = ts_input[:, None] # [T,C]
455
 
456
  ts_len = ts_input.shape[0]
457
+ ts_channel = ts_input.shape[1]
458
 
459
  if sr is None or sr == 0: # if no sr provided
460
  sr = ts_len / 4
 
462
  ts_values.append(ts_input)
463
  ts_sr.append(sr)
464
  ts_lens.append(ts_len)
465
+ ts_channels.append(ts_channel)
466
 
467
+ ts_channels = np.array(ts_channels)
468
  ts_lens = np.array(ts_lens)
469
  ts_sr = np.array(ts_sr)
470
  num_ts_tokens = self._get_num_ts_tokens(sampling_rates=ts_sr, ts_lens=ts_lens)
471
  return BatchFeature(
472
+ data={
473
+ "ts_values": ts_values,
474
+ "ts_sr": ts_sr,
475
+ "ts_lens": ts_lens,
476
+ "ts_channels": ts_channels,
477
+ "num_ts_tokens": num_ts_tokens,
478
+ }
479
  )
480
 
481
  def _get_num_ts_tokens(self, sampling_rates, ts_lens):
482
+ chunk_size, num_qformer_query = self.chunk_size, self.num_query
483
+ ts_len = torch.from_numpy(ts_lens)
484
+ chunk_num = ts_len // chunk_size
485
+ tail_len = ts_len - chunk_num * chunk_size
486
+ subrate = torch.clamp(ts_len / 500, min=1.0)
487
+ stride = subrate * num_qformer_query
488
+ patch_size = torch.ceil(stride)
489
+ num_ts_tokens = (
490
+ (
491
+ chunk_num * ((torch.ceil((chunk_size - patch_size) / stride + 1) * num_qformer_query + 1) // 2)
492
+ + (torch.ceil((tail_len - patch_size) / stride + 1) * num_qformer_query + 1) // 2
493
+ )
494
+ .long()
495
+ .tolist()
496
+ )
497
  return num_ts_tokens
498
 
499
 
preprocessor_config.json → processor_config.json RENAMED
@@ -16,8 +16,10 @@
16
  0.5,
17
  0.5
18
  ],
19
- "processor_class": "Qwen3VLProcessor",
20
- "image_processor_type": "Qwen2VLImageProcessorFast",
 
 
21
  "auto_map": {
22
  "AutoProcessor": "processing_interns2_preview.InternS2PreviewProcessor"
23
  }
 
16
  0.5,
17
  0.5
18
  ],
19
+ "chunk_size": 12800,
20
+ "patch": 50,
21
+ "num_query": 2,
22
+ "ts_signals_do_normalize": false,
23
  "auto_map": {
24
  "AutoProcessor": "processing_interns2_preview.InternS2PreviewProcessor"
25
  }