InternLM · HF · 上海 AI Lab

Intern-S2-Preview-397B

Intern-S2-Preview-397B

二〇二六年八月二十六日 · 英文原文

上海人工智能实验室推出 Intern-S2-Preview-397B 多模态基础模型,在预训练、强化学习任务覆盖和交互式 agent 环境三个维度进行扩展。该模型通过视觉-语言预训练直接从科学文献原始页面学习,联合建模符号语义与视觉关系;在超过 20 个科学领域扩展强化学习任务并联合训练,在通用推理和生物分子相互作用设计、材料结构生成等专业任务上表现强劲;通过将多个 agent 框架连接至大规模沙盒环境进行黑盒 agent 强化学习,提升了长周期任务能力。模型支持 256K tokens 文本推理和 64K tokens 多模态推理,可通过 LMDeploy、vLLM、SGLang 部署,并兼容 OpenAI 和 Anthropic 接口接入 agent 框架。

Intern-S2-Preview-397B

💻Github Repo🤗Model Collections💬Online Chat

引言

我们推出 Intern-S2-Preview-397B,这是我们在科学智能和长周期 agent 领域能力最强的多模态基础模型。Intern-S2-Preview-397B 在三个关键维度上进行了扩展:预训练、强化学习任务覆盖范围以及交互式 agent 环境。通过将新的视觉-语言预训练范式与大规模多任务强化学习及长周期 agent 强化学习相结合,Intern-S2-Preview-397B 在通用推理、科学问题求解和 agent 能力方面实现了阶跃式提升。

特性

性能

我们在多个 benchmark 上评估了 Intern-S2-Preview-397B,包括通用数据集和科学数据集。以下是与近期 VLM 和 LLM 的性能对比。

general_performance scientific_performance

注意:下划线表示开源模型中的最佳性能,粗体表示所有模型中的最佳性能。

我们使用 OpenCompassVLMEvalKitAgentCompass 评估所有模型。对于文本推理 benchmark,Intern-S2-Preview-397B 的最大推理长度为 256K tokens;对于多模态 benchmark,最大推理长度为 64K tokens。

快速开始

采样参数

我们建议使用以下超参数以获得更好的结果

top_p = 0.95
top_k = 50
min_p = 0.0
temperature = 0.8

服务部署

Intern-S2-Preview-397B 可以使用以下任一 LLM 推理框架进行部署:

这些框架的详细部署示例可在模型部署指南中找到。

高级用法

工具调用

工具调用让模型能够通过调用外部工具和 API 来扩展其能力。下面的示例展示了如何使用 OpenAI 兼容的 API(基于 lmdeploy api server)来获取最新的天气预报。



from openai import OpenAI
import json


def get_current_temperature(location: str, unit: str = "celsius"):
    """Get current temperature at a location.

    Args:
        location: The location to get the temperature for, in the format "City, State, Country".
        unit: The unit to return the temperature in. Defaults to "celsius". (choices: ["celsius", "fahrenheit"])

    Returns:
        the temperature, the location, and the unit in a dict
    """
    return {
        "temperature": 26.1,
        "location": location,
        "unit": unit,
    }


def get_temperature_date(location: str, date: str, unit: str = "celsius"):
    """Get temperature at a location and date.

    Args:
        location: The location to get the temperature for, in the format "City, State, Country".
        date: The date to get the temperature for, in the format "Year-Month-Day".
        unit: The unit to return the temperature in. Defaults to "celsius". (choices: ["celsius", "fahrenheit"])

    Returns:
        the temperature, the location, the date and the unit in a dict
    """
    return {
        "temperature": 25.9,
        "location": location,
        "date": date,
        "unit": unit,
    }

def get_function_by_name(name):
    if name == "get_current_temperature":
        return get_current_temperature
    if name == "get_temperature_date":
        return get_temperature_date

tools = [{
    'type': 'function',
    'function': {
        'name': 'get_current_temperature',
        'description': 'Get current temperature at a location.',
        'parameters': {
            'type': 'object',
            'properties': {
                'location': {
                    'type': 'string',
                    'description': 'The location to get the temperature for, in the format \'City, State, Country\'.'
                },
                'unit': {
                    'type': 'string',
                    'enum': [
                        'celsius',
                        'fahrenheit'
                    ],
                    'description': 'The unit to return the temperature in. Defaults to \'celsius\'.'
                }
            },
            'required': [
                'location'
            ]
        }
    }
}, {
    'type': 'function',
    'function': {
        'name': 'get_temperature_date',
        'description': 'Get temperature at a location and date.',
        'parameters': {
            'type': 'object',
            'properties': {
                'location': {
                    'type': 'string',
                    'description': 'The location to get the temperature for, in the format \'City, State, Country\'.'
                },
                'date': {
                    'type': 'string',
                    'description': 'The date to get the temperature for, in the format \'Year-Month-Day\'.'
                },
                'unit': {
                    'type': 'string',
                    'enum': [
                        'celsius',
                        'fahrenheit'
                    ],
                    'description': 'The unit to return the temperature in. Defaults to \'celsius\'.'
                }
            },
            'required': [
                'location',
                'date'
            ]
        }
    }
}]



messages = [
    {'role': 'user', 'content': 'Today is 2024-11-14, What\'s the temperature in San Francisco now? How about tomorrow?'}
]

openai_api_key = "EMPTY"
openai_api_base = "http://0.0.0.0:23333/v1"
client = OpenAI(
    api_key=openai_api_key,
    base_url=openai_api_base,
)
model_name = client.models.list().data[0].id
response = client.chat.completions.create(
    model=model_name,
    messages=messages,
    max_tokens=32768,
    temperature=0.8,
    top_p=0.95,
    extra_body=dict(spaces_between_special_tokens=False),
    tools=tools)
print(response.choices[0].message)
messages.append(response.choices[0].message)

for tool_call in response.choices[0].message.tool_calls:
    tool_call_args = json.loads(tool_call.function.arguments)
    tool_call_result = get_function_by_name(tool_call.function.name)(**tool_call_args)
    tool_call_result = json.dumps(tool_call_result, ensure_ascii=False)
    messages.append({
        'role': 'tool',
        'name': tool_call.function.name,
        'content': tool_call_result,
        'tool_call_id': tool_call.id
    })

response = client.chat.completions.create(
    model=model_name,
    messages=messages,
    temperature=0.8,
    top_p=0.95,
    extra_body=dict(spaces_between_special_tokens=False),
    tools=tools)
print(response.choices[0].message)

在思考模式与非思考模式间切换

Intern-S2-Preview-397B 默认启用思考模式,以增强模型的推理能力,生成更高质量的回复。可以通过在 tokenizer.apply_chat_template 中设置 enable_thinking=False 来禁用此功能。

text = tokenizer.apply_chat_template(
    messages,
    tokenize=False,
    add_generation_prompt=True,
    enable_thinking=False  # think mode indicator
)

在服务 Intern-S2-Preview-397B 模型时,可以通过调整请求中的 enable_thinking 参数来动态控制思考模式。

from openai import OpenAI
import json

messages = [
{
    'role': 'user',
    'content': 'who are you'
}, {
    'role': 'assistant',
    'content': 'I am an AI'
}, {
    'role': 'user',
    'content': 'AGI is?'
}]

openai_api_key = "EMPTY"
openai_api_base = "http://0.0.0.0:23333/v1"
client = OpenAI(
    api_key=openai_api_key,
    base_url=openai_api_base,
)
model_name = client.models.list().data[0].id

response = client.chat.completions.create(
    model=model_name,
    messages=messages,
    temperature=0.8,
    top_p=0.95,
    max_tokens=2048,
    extra_body={
        "chat_template_kwargs": {"enable_thinking": False}
    }
)
print(json.dumps(response.model_dump(), indent=2, ensure_ascii=False))

注意:我们不建议在 agent 任务中禁用思考模式。

时间序列演示

时间序列推理目前仅在 LMDeploy 中支持。要开始使用,请按照模型部署指南使用 LMDeploy 下载并部署 Intern-S2-Preview-397B。 以下是从时间序列信号文件中检测地震事件的示例。也支持其他数据类型和功能。

请注意:此演示与 Intern-S1-Pro 中的演示略有不同。主要区别在于,在 messages 的 content 中,您需要先提供 time_series_url,然后是文本 prompt。请根据此演示调整您的实现。

from openai import OpenAI
from lmdeploy.vl.utils import encode_time_series_base64

openai_api_key = "EMPTY"
openai_api_base = "http://0.0.0.0:8000/v1"
client = OpenAI(
    api_key=openai_api_key,
    base_url=openai_api_base,
)
model_name = client.models.list().data[0].id


def send_base64(file_path: str, sampling_rate: int = 100):
    """base64-encoded time-series data."""

    # encode_time_series_base64 accepts local file paths and http urls,
    # encoding time-series data (.npy, .csv, .wav, .mp3, .flac, etc.) into base64 strings.
    base64_ts = encode_time_series_base64(file_path)

    messages = [
        {
            "role": "user",
            "content": [
                {
                    "type": "time_series_url",
                    "time_series_url": {
                        "url": f"data:time_series/npy;base64,{base64_ts}",
                        "sampling_rate": sampling_rate
                    },
                },
                {
                    "type": "text",
                    "text": "Please determine whether an Earthquake event has occurred in the provided time-series data. If so, please specify the starting time point indices of the P-wave and S-wave in the event."
                },
            ],
        }
    ]

    return client.chat.completions.create(
        model=model_name,
        messages=messages,
        temperature=0,
        max_tokens=200,
        extra_body={
            "chat_template_kwargs": {"enable_thinking": False}
        }
    )


def send_http_url(url: str, sampling_rate: int = 100):
    """http(s) url pointing to the time-series data."""
    messages = [
        {
            "role": "user",
            "content": [
                {
                    "type": "time_series_url",
                    "time_series_url": {
                        "url": url,
                        "sampling_rate": sampling_rate
                    },
                },
                {
                    "type": "text",
                    "text": "Please determine whether an Earthquake event has occurred in the provided time-series data. If so, please specify the starting time point indices of the P-wave and S-wave in the event."
                },
            ],
        }
    ]

    return client.chat.completions.create(
        model=model_name,
        messages=messages,
        temperature=0,
        max_tokens=200,
        extra_body={
            "chat_template_kwargs": {"enable_thinking": False}
        }
    )


def send_file_url(file_path: str, sampling_rate: int = 100):
    """file url pointing to the time-series data."""
    messages = [
        {
            "role": "user",
            "content": [
                {
                    "type": "time_series_url",
                    "time_series_url": {
                        "url": f"file://{file_path}",
                        "sampling_rate": sampling_rate
                    },
                },
                {
                    "type": "text",
                    "text": "Please determine whether an Earthquake event has occurred in the provided time-series data. If so, please specify the starting time point indices of the P-wave and S-wave in the event."
                },
            ],
        }
    ]

    return client.chat.completions.create(
        model=model_name,
        messages=messages,
        temperature=0,
        max_tokens=200,
        extra_body={
            "chat_template_kwargs": {"enable_thinking": False}
        }
    )

response = send_base64("./0092638_seism.npy")
# response = send_http_url("https://huggingface.co/internlm/Intern-S1-Pro/raw/main/0092638_seism.npy")
# response = send_file_url("./0092638_seism.npy")

print(response.choices[0].message)

Agent 集成

Intern-S2-Preview-397B 可以通过两种方式接入 agent 框架:连接到自托管部署,或调用官方 InternLM API。下面我们介绍这两种方式,并给出 agent 框架(OpenClaw、Hermes 等)和 Claude Code 的示例。

1. 自托管部署(以 LMDeploy 为例)

首先,按照模型部署指南使用 LMDeploy 服务模型。下面的示例假设服务器运行在 http://0.0.0.0:23333

连接 Agent 框架

大多数 agent 框架(OpenClaw、Hermes 等)接受 OpenAI 兼容的端点。将它们指向 LMDeploy 服务器的 base url http://0.0.0.0:23333/v1

您可以使用以下命令检查连接:

curl http://0.0.0.0:23333/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer EMPTY" \
  -d '{
    "model": "internlm/Intern-S2-Preview-397B",
    "messages": [
      {"role": "user", "content": "Hello"}
    ],
    "temperature": 0.8,
    "top_p": 0.95
  }'

或者,您可以使用环境变量配置您的 agent 框架:

export OPENAI_API_KEY=EMPTY
export OPENAI_BASE_URL=http://0.0.0.0:23333/v1
export OPENAI_MODEL=internlm/Intern-S2-Preview-397B

请记得使用 --tool-call-parser interns2-preview 启动 LMDeploy,以便正确解析工具调用。

连接 Claude Code

LMDeploy 暴露了一个 Anthropic 兼容的 /v1/messages 端点,Claude Code 可以直接与之通信。将以下内容添加到 ~/.claude/settings.json

{
  "env": {
    "ANTHROPIC_BASE_URL": "http://127.0.0.1:23333",
    "ANTHROPIC_AUTH_TOKEN": "dummy",
    "ANTHROPIC_MODEL": "internlm/Intern-S2-Preview-397B",
    "ANTHROPIC_CUSTOM_MODEL_OPTION": "internlm/Intern-S2-Preview-397B"
  }
}

有关完整指南(curl 验证、模型路由、故障排除),请参阅 LMDeploy × Claude Code

2. 官方 Intern API

如果您不想自托管,可以使用官方 Intern API。在 internlm.intern-ai.org.cn 注册并创建一个 API token(sk-xxxxxxxx)。

连接 Agent 框架

该服务是 OpenAI 兼容的,因此任何 agent 框架都可以使用。您可以在 CLI 或配置文件中将 base url 设置为 https://chat.intern-ai.org.cn/api/v1,模型名称设置为 intern-s2-preview-397b

您可以使用以下命令检查连接:

curl https://chat.intern-ai.org.cn/api/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-xxxxxxxx" \
  -d '{
    "model": "intern-s2-preview-397b",
    "messages": [
      {"role": "user", "content": "Hello"}
    ],
    "temperature": 0.8,
    "top_p": 0.95
  }'

请参阅 Intern API 文档了解当前端点、可用的模型名称、速率限制和高级参数。

连接 Claude Code

Claude Code 可以通过将 ANTHROPIC_BASE_URL 指向 Intern 的 Anthropic 兼容网关来路由到官方 Intern API:

{
  "env": {
    "ANTHROPIC_BASE_URL": "https://chat.intern-ai.org.cn",
    "ANTHROPIC_AUTH_TOKEN": "your-api-token",
    "ANTHROPIC_MODEL": "intern-s2-preview-397b",
    "ANTHROPIC_SMALL_FAST_MODEL": "intern-s2-preview-397b"
  }
}

然后使用以下命令启动 claude code:

claude --model intern-s2-preview-397b

有关逐步设置,请参阅 Intern API × Claude Code 集成

译自 InternLM · HF · 上海 AI Lab · 录于 二〇二六年八月二十六日