商汤大模型食用指南

简介

4月23日商汤科技在上海发布“日日新SenseNova”5.0多模态大模型系列,采用混合专家(MoE)架构,支持多达10T Tokens中英文与训练数据,推理合成数据高达数千亿Token,推理时上下文窗口可以有效到200K左右,拥有端侧扩散和语言模型,知识、推理、数学、代码等综合能力全面对标GPT-4 Turbo。

简单上手

注册

访问 注册页 注册,注册通过后会直接登录,并赠送了 5kw token包(600元后付费代金券),有效期1个月,请及时使用。


开通服务

访问 大模型页 阅读服务条款后勾选同意,点击 开通服务


获取密钥

访问 密钥页,点击 创建访问密钥,并注意复制保存,你也可以下载csv到本地


image

复制到的Access Key包括Access Key ID和Access Key Secret

如何使用

部署worker

worker.js
addEventListener("fetch", event => {
  event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
  const url = new URL(request.url);

  if (url.pathname === "/v1/chat/completions" && request.method === "POST") {
    const contentType = request.headers.get("Content-Type");
    const authorization = request.headers.get("Authorization");

    if (contentType !== "application/json" || !authorization) {
      return new Response("Bad Request: Missing required headers", { status: 400 });
    }

    let body;
    try {
      body = await request.json();
    } catch (e) {
      return new Response("Bad Request: Invalid JSON", { status: 400 });
    }

    if (!body.model || !body.messages || !Array.isArray(body.messages)) {
      return new Response("Bad Request: Missing required parameters", { status: 400 });
    }

    // 替换 max_tokens 为 max_new_tokens
    if (body.max_tokens) {
      body.max_new_tokens = body.max_tokens;
      delete body.max_tokens;
    }

    // 添加 plugins 
    body.plugins = {
      "web_search": {
        "search_enable": true,
        "result_enable": false
      }
    };

    const apiUrl = "https://api.sensenova.cn/v1/llm/chat-completions";
    const newRequest = new Request(apiUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": authorization
      },
      body: JSON.stringify(body)
    });

    const response = await fetch(newRequest);

    return handleResponse(response, body.stream, body.model);
  }

  return new Response("Not Found", { status: 404 });
}

async function handleResponse(response, isStream, model) {
  const headers = new Headers(response.headers);
  headers.set("Access-Control-Allow-Origin", "*");

  if (isStream) {
    return handleStreamResponse(response, model, headers);
  } else {
    return handleNonStreamResponse(response, model, headers);
  }
}

function handleStreamResponse(response, model, headers) {
  const reader = response.body.getReader();

  const stream = new ReadableStream({
    async start(controller) {
      let buffer = '';

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        buffer += new TextDecoder().decode(value);

        let lines = buffer.split('\n');
        buffer = lines.pop();

        for (const line of lines) {
          if (line.trim() === '') continue;
          if (line.trim() === 'data: [DONE]') {
            controller.enqueue(new TextEncoder().encode('data: [DONE]\n\n'));
            continue;
          }

          if (line.startsWith('data:')) {
            const json = JSON.parse(line.slice(5));
            const newJson = {
              id: json.data.id,
              object: "chat.completion.chunk",
              created: Date.now(),
              model: model,
              choices: json.data.choices.map(choice => ({
                index: choice.index,
                delta: { content: choice.delta.trim() },
                finish_reason: choice.finish_reason
              }))
            };
            controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify(newJson)}\n\n`));
          }
        }
      }

      controller.close();
    }
  });

  return new Response(stream, { headers });
}

async function handleNonStreamResponse(response, model, headers) {
  const responseData = await response.json();
  const newResponseData = {
    id: responseData.data.id,
    object: "chat.completion",
    created: Date.now(),
    model: model,
    choices: responseData.data.choices.map(choice => ({
      index: choice.index,
      message: { content: choice.message.trim() },
      finish_reason: choice.finish_reason
    }))
  };

  return new Response(JSON.stringify(newResponseData), {
    headers: { "Content-Type": "application/json" }
  });
}

生成令牌

生成的令牌1个月有效

jwt.py
import time
import jwt

ak = "aaaaaaaa" # 替换为您的 Access Key ID
sk = "aaaaaaaa" # 替换为您的 Access Key Secret

def encode_jwt_token(ak, sk):
    headers = {
        "alg": "HS256",
        "typ": "JWT"
    }
    payload = {
        "iss": ak,
        "exp": int(time.time()) + 30 * 24 * 60 * 60, # 当前时间+30天
        "nbf": int(time.time()) - 5 # 当前时间-5秒
    }
    token = jwt.encode(payload, sk, headers=headers)
    return token

authorization = encode_jwt_token(ak, sk)
print(authorization) # 打印生成的API_TOKEN

部署oneapi

选择OpenAI或者自定义渠道,

  • baseurl: 你的worker地址

  • model: nova-ptc-xl-v1,nova-ptc-xs-v1,nova-embedding-stable,nova-ptc-s-v2,SenseChat,SenseChat-Vision,SenseChat-32K,SenseChat-Character,SenseChat-128K,SenseChat-FunctionCall,SenseChat-Turbo,SenseChat-5,SenseChat-5-Cantonese,SenseChat-Character-Pro

  • key: 你的令牌

如果使用中遇到问题,可根据 错误码 快速处理

参考链接

10 个赞

赠送额度一个月。。。没啥兴趣

2 个赞

能不能用另说,给大佬点个赞

1 个赞

7月2日-7月31日 这时间算了.

1 个赞

顶楼顶楼 :hugs:

1 个赞

应该是从注册时间算起1个月有效

额度挺多的,跑沉浸式翻译够用

1 个赞

不知道翻译质量如何呢?额度多,但是限制1个月用完…

额度有时效性,像我使用翻译场景也不多的人,拿来没用

现在每个模型都说自己对标 gpt-4,实际上真正能对标的又有几个。。。

1 个赞

1个月,还要86手机,太苛刻了

嗯 我想表达就是一个月 。有点短和其他国内模型风格不一样。

这么短…

对,人家可是研究了那么多年,投入了那么多真金白银的。