编组
控制台用户中心

孟子生成式大模型

文档中心

孟子生成式大模型

调用说明

请求地址#

发送 POST 请求到:

https://open.langboat.com/chat

通信协议#

澜舟科技孟子 GPT 服务所提供的 API 接口均通过 HTTPS 进行通信,提供高安全性的通信通道。

调用量统计#

孟子 GPT 按实际调用服务的输入及输出 token 数的总和进行收费。

token 是模型用来处理自然语言的基本单位,一个 token 可以理解成一个汉语词组或者一个英文单词,一般情况下,澜舟孟子 GPT 模型 token 数量和字数的换算比例大概为 1:1.33 左右。

示例: 你知道牛顿吗 对应 token 数为 4。

请求参数#

请求头#

请求头参数是否必须描述
Accept固定值 application/json
Authorization用于验证请求合法性的认证信息,值为 AccessKey:signature 格式。
Content-Type固定值 application/json
Content-MD5HTTP 协议消息体的 128-bit MD5 散列值转换成 Base64 编码的结果。
Date请求时间,GMT 格式,如: Wed, 20 Apr. 2022 17:01:00 GMT。
x-langboat-signature-nonce唯一随机数,用于防止网络重放攻击。在不同请求中要使用不同的随机数值。
x-langboat-signature-method签名方法,目前只支持 HMAC-SHA256
签名计算方法#
  1. 计算 body 的 MD5 值,然后转换为 Base64 编码,编码后的值设置到 Content-MD5 Header。

计算示例:

  • body
{
"model": "mengzi-lite",
"messages": [
{
"role": "user",
"content": "你知道牛顿吗"
}
],
"n": 1,
"max_tokens": 1024,
"user": ""
}
  • MD5(body) = byte(05e24d61412c8cd0403be206f644e8dc)
  • Base64(MD5(body)) = BeJNYUEsjNBAO+IG9kTo3A=

Content-MD5 Header: Content-MD5: BeJNYUEsjNBAO+IG9kTo3A=

  1. 使用请求中的 Header 参数构造待签名的 StringToSign:
StringToSign =
HTTP-Verb + "\n" + //HTTP-Verb只支持POST
Accept + “\n” + //Accept为application/json
Content-MD5 + "\n" + //第1步中计算出来的MD5值
Content-Type + "\n" + //Content-Type值为application/json
Date + "\n" + //Date值为GMT时间
x-langboat-signature-method + "\n" + // 只支持 HMAC-SHA256
x-langboat-signature-nonce + "\n";

StringToSign 示例:

POST
application/json
BeJNYUEsjNBAO+IG9kTo3A=
application/json
Wed, 20 Apr 2022 02:50:21 GMT
HMAC-SHA256
53371
  1. 使用请求中的 Queries 构造待签名的 queryToSign。将 query 字符串(?后的所有参数)根据字典排序升序排列并以&分隔,示例如下:
a=b&c=d

孟子GPT API 中 所有参数均放在 body,所以这里可以传空。

  1. 将上两步构造的规范化字符串按照下面的规则构造成待签名的字符串。
stringToSign = headerStringToSign + queryToSign;
  1. 计算签名 signature。按照 RFC2104 的定义,计算待签名字符串 stringToSign 的 HMAC 值,按照 Base64 编码规则把 HMAC 值编码成字符串,并在前面加上 AccessKey ,即得到签名值(Authorization),示例如下:
Signature = Base64(HMAC-SHA256( AccessSecret, UTF-8-Encoding-Of(stringToSign)))
Authorization = AccessKey + ":" + Signature

Signature 示例:po/vsPI0RcvY/eu4bohhxxADHyPj4/rcglLTQEBtHQM=

Authorization 示例: Authorization: 7Bo9ByyiTWRC1Y8KJJQ9cWtNpZLmrgyb:po/vsPI0RcvY/eu4bohhxxADHyPj4/rcglLTQEBtHQM=

Body 参数#

Body 参数类型是否必须描述
modelstring模型名称,示例 mengzi-lite,详细见模型列表
messagesList(message)聊天上下文信息。
temperaturefloat基于温度系数的采样系数,值越大,输出越随机。有些模型不支持,详细见模型列表
top_pfloat核采样,功能类似 temperature,两个值最好不要同时修改。有些模型不支持,详细见模型列表
nint返回数量,取值范围 [1,3],默认 1。
streambool是否以流式接口的形式返回数据,默认 false,有些模型不支持,详细见模型列表
max_tokensint生成 tokens 最大数量,详细见模型列表
userstring用户的标识,可用于检测滥用行为,以防止接口恶意调用。

特别说明#

模型列表#
模型模型名称最大content长度是否支持 stream是否支持 temperature是否支持 top_p是否支持max_tokens
mengzi-lite孟子大模型-轻量4000 字符是,默认 0.1,取值范围 [0,1]。是,默认 0.95,取值范围 [0,1]。是,默认 4096,取值范围 [1,4096]。
mengzi-fin孟子大模型-金融1500 字符是,默认 0.2,取值范围 [0,1]。是,默认 0.95,取值范围 [0,1]。是,默认 2048,取值范围 [1,4096]。
mengzi-code孟子大模型-编程5000 字符是,默认 0.2,取值范围 [0,1]。是,默认 0.95,取值范围 [0,1]。是,默认 4096,取值范围 [1,4096]。
messages#
  • messages 成员不能为空,1个成员表示单轮对话,多个成员表示多轮对话。
  • 最后一个 message 为当前请求的信息,前面的 message 为历史对话信息。
  • 必须为奇数个成员,成员中 message 的 role 必须依次为 user、assistant。
  • 最大content长度指此轮对话message可以处理的最大长度,超过最大长度的,系统会依次遗忘最早的历史对话,直到content总长度不超过最大长度限制。

Body 示例#

{
"model": "mengzi-lite",
"messages": [
{
"role": "user",
"content": "你知道牛顿吗"
}
],
"temperature": 0.1,
"top_p": 0.05,
"n": 1,
"stream": false,
"max_tokens": 4096,
"user": ""
}

请求示例:

POST https://open.langboat.com/chat
Content-Type: application/json
Content-MD5: BeJNYUEsjNBAO+IG9kTo3A==
Date: Tue, 19 Apr 2022 10:03:46 GMT
Accept: application/json
x-langboat-signature-method: HMAC-SHA256
x-langboat-signature-nonce: 43785
Authorization: 7Bo9ByyiTWRC1Y8KJJQ9cWtNpZLmrgyb:po/vsPI0RcvY/eu4bohhxxADHyPj4/rcglLTQEBtHQM=

响应#

成功的响应体是一个 JSON, 示例:

{
"id": "chatcmpl-1135c2751ec9c45ec5d525303500d548",
"object": "chat.completion",
"created": 1692865424,
"model": "mengzi-lite",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "当然了!伊萨克·牛顿(Isaac Newton)是一位伟大的英国物理学家、数学家和自然哲学家,被认为是现代科学之父之一。他最著名的成就是发现了万有引力定律以及三大运动定律,这些理论对我们理解宇宙产生了深远影响。此外,他在光学、微积分等领域也做出了重要贡献。"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 4,
"completion_tokens": 99,
"total_tokens": 103
}
}

响应参数#

名称类型描述
idstring本次接口调用会话id
objectstring回包类型, 非 stream:chat.completion, stream:chat.chunk
createdint时间戳
modelstring模型名称
choicesList(choice)聊天详情
usageusage本次调用统计信息

choice#

名称类型描述
index索引对应请求参数 n
messageList(message)结构同输入 message
finish_reasonstring回答结束的原因

stream 和非 stream 模式,响应参数不同,详细内容参考示例描述。#

  • 非 stream 模式下,响应参数为以上字段的完整 json 包。
  • stream 模式下,message对应字段为delta

usage#

名称类型描述
prompt_tokensint问题的 token 数
completion_tokensint回答的 token 数
total_tokensint总的 token 数

响应状态码、业务编码#

下面是可能的 HTTP 响应状态码、业务(错误)编码:

HTTP 状态码业务编码描述
2000返回成功
40010400请求异常
40110401鉴权失败,核对 AccessKey 和 AccessSecret 是否正确
40310403权限不足,查看是否开通服务
42210422参数错误,核对请求参数
42910429超过请求限制(QPS,字符数,次数超过限制,当前排队人数过多)
50010500服务异常

错误响应示例

  • 鉴权失败
{
"error": {
"code": 10403,
"message": "AccessKey 不存在, 请检查 AccessKey 是否正确",
"requestId": "6f233f3e276bc1ba2ffb0069df62cd1b"
}
}
  • 权限不足
{
"error": {
"code": 10403,
"message": "权限不足,查看是否开通服务",
"requestId": "6f233f3e276bc1ba2ffb0069df62cd1b"
}
}

stream 示例#

stream 模式下,按照句子片段进行输出。如果生成结果比较短,可能只有一个片段。

多片段示例#

curl 'http://open.langboat.com/chat' \
--header 'Content-MD5: WkwTeY7YOwSSeyB09sF6ow==' \
--header 'x-langboat-signature-method: HMAC-SHA256' \
--header 'x-langboat-signature-nonce: 43785' \
--header 'Authorization: mWve3ivAD1NljBkCj7Pk2eZQQB3PmMt6:MyJ/1mthTM51zHVXOr13+8RhjMAuGIhKttKFr+nb6hs=' \
--header 'Date: Thu, 16 Jun 2022 13:09:33 GMT' \
--header 'Content-Type: application/json' \
--data '{
"model": "mengzi-lite",
"messages": [
{
"role":"user",
"content":"你知道牛顿吗"
}
],
"temperature": 1,
"top_p": 0,
"n": 1,
"stream": true,
"max_tokens": 4096,
"user": ""
}'
多片段响应#
id: 0-0
data: {"id":"chatcmpl-dac45d8d2fd528f46afdda15be6a4e63","object":"chat.completion.chunk","created":1692865308,"model":"mengzi-lite","choices":[{"index":0,"delta":{"content":"当然了!伊萨克·牛顿(Isaac Newton)是一位伟大的英国物理学家、数学家和自然哲学家,被认为是现代科学之父之一。"},"finish_reason":null}]}
id: 0-1
data: {"id":"chatcmpl-dac45d8d2fd528f46afdda15be6a4e63","object":"chat.completion.chunk","created":1692865309,"model":"mengzi-lite","choices":[{"index":0,"delta":{"content":"他最著名的成就是发现了万有引力定律以及三大运动定律,这些理论对我们理解宇宙产生了深远影响。"},"finish_reason":null}]}
id: 0-2
data: {"id":"chatcmpl-dac45d8d2fd528f46afdda15be6a4e63","object":"chat.completion.chunk","created":1692865309,"model":"mengzi-lite","choices":[{"index":0,"delta":{"content":"此外,他在光学、微积分等领域也做出了重要贡献。"},"finish_reason":null}]}
data: [DONE]

单片段示例#

curl 'http://open.langboat.com/chat' \
--header 'Content-MD5: WkwTeY7YOwSSeyB09sF6ow==' \
--header 'x-langboat-signature-method: HMAC-SHA256' \
--header 'x-langboat-signature-nonce: 43785' \
--header 'Authorization: mWve3ivAD1NljBkCj7Pk2eZQQB3PmMt6:MyJ/1mthTM51zHVXOr13+8RhjMAuGIhKttKFr+nb6hs=' \
--header 'Date: Thu, 16 Jun 2022 13:09:33 GMT' \
--header 'Content-Type: application/json' \
--data '{
"model": "mengzi-lite",
"messages": [
{
"role":"user",
"content":"你好"
}
],
"temperature": 0.1,
"top_p": 0.05,
"n": 1,
"stream": true,
"max_tokens": 4096,
"user": ""
}'
单片段响应#
id: 0-0
data: {"id":"chatcmpl-dac45d8d2fd528f46afdda15be6a4e63","object":"chat.completion.chunk","created":1692865308,"model":"mengzi-lite","choices":[{"index":0,"delta":{"content":"你好,有什么需要帮助的吗?"},"finish_reason":null}]}
data: [DONE]

示例代码#

Java(JDK>=11)#

Dependencies:

<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.0</version>
</dependency>
</dependencies>

Code:

package com.langboat.client;
import com.fasterxml.jackson.databind.ObjectMapper;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.*;
import java.util.stream.Stream;
/**
* 澜舟开放平台 chat 客户端
*/
public class LangboatOpenChatClient {
private final String accessKey;
private final String accessSecret;
private final String url;
private final ObjectMapper objMapper = new ObjectMapper();
public LangboatOpenChatClient(String accessKey, String accessSecret) {
this.accessKey = accessKey;
this.accessSecret = accessSecret;
this.url = "https://open.langboat.com";
}
public LangboatOpenChatClient(String accessKey, String accessSecret, String url) {
this.accessKey = accessKey;
this.accessSecret = accessSecret;
this.url = url;
}
/*
* 计算 MD5 + Base64
*/
private String MD5Base64(String s) {
if (s == null)
return null;
String encodeStr = "";
byte[] utfBytes = s.getBytes();
MessageDigest mdTemp;
try {
mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(utfBytes);
byte[] md5Bytes = mdTemp.digest();
encodeStr = Base64.getEncoder().encodeToString(md5Bytes);
} catch (Exception e) {
throw new Error("Failed to generate MD5 : " + e.getMessage());
}
return encodeStr;
}
/*
* 计算 HMAC-SHA256 + Base64 编码
*/
private String HMACSha256Base64(String data, String key) {
String result;
try {
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA256");
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(data.getBytes());
result = Base64.getEncoder().encodeToString(rawHmac);
} catch (Exception e) {
throw new Error("Failed to generate HMAC : " + e.getMessage());
}
return result;
}
/*
* 获取时间
*/
private String toGMTString(Date date) {
SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));
return df.format(date);
}
public Object chat(Map<String, String> queries, Map<String, Object> data) throws Exception {
String body = this.objMapper.writeValueAsString(data);
String method = "POST";
String accept = "application/json";
String contentType = "application/json";
String date = toGMTString(new Date());
// 1.对body做MD5+BASE64加密
String bodyMd5 = MD5Base64(body);
String nonce = "" + (int) (Math.random() * 65535);
String headerToSign = method + "\n" + accept + "\n" + bodyMd5 + "\n"
+ contentType + "\n" + date + "\n"
+ "HMAC-SHA256\n"
+ nonce + "\n";
// 2.计算 queryToSign
List<String> queriesList = new ArrayList<>();
queries.forEach((k, v) -> queriesList.add(k + "=" + v));
Collections.sort(queriesList);
String queryToSign = String.join("&", queriesList);
// 3.计算 stringToSign
String stringToSign = headerToSign + queryToSign;
// 4.计算 HMAC-SHA256 + Base64
String signature = HMACSha256Base64(stringToSign, this.accessSecret);
// 5.得到 authorization header 值
String authorization = this.accessKey + ":" + signature;
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(this.url + "/chat"))
.timeout(Duration.ofSeconds(60))
.header("Accept", accept)
.header("Content-Type", contentType)
.header("Content-MD5", bodyMd5)
.header("Date", date)
.header("Authorization", authorization)
.header("x-langboat-signature-nonce", nonce)
.header("x-langboat-signature-method", "HMAC-SHA256")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpClient client = HttpClient.newHttpClient();
if ((boolean) data.get("stream")) {
final HttpResponse<Stream<String>> response = client.send(request, HttpResponse.BodyHandlers.ofLines());
if (response.statusCode() == 200) {
response.body().forEach(System.out::println);
return response.body();
} else {
System.out.println(response.body());
throw new RuntimeException("请求失败");
}
} else {
final HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
System.out.println(response.body());
return response.body();
} else {
System.out.println(response.statusCode());
System.out.println(response.body());
throw new RuntimeException("请求失败");
}
}
}
public static void main(String[] args) throws Exception {
LangboatOpenChatClient client = new LangboatOpenChatClient("YourAccessKey", "YourAccessSecret");
// 通用中英翻译
Map<String, String> queries = Map.of();
Map<String, Object> data = Map.of(
"model", "mengzi-lite",
"stream", true,
"messages", List.of(Map.of(
"role", "user",
"content", "你知道牛顿吗"
)),
"max_tokens", 1024,
"user", ""
);
Object o = client.chat(queries, data);
System.out.println(o);
}
}

Python (>= 3.6)#

# -*- coding: utf-8 -*-
import base64
import datetime
import hashlib
import hmac
import json
import random
import requests
class LangboatOpenClient:
"""澜舟开放平台客户端"""
def __init__(self,
access_key: str,
access_secret: str,
url: str = "https://open.langboat.com"):
self.access_key = access_key
self.access_secret = access_secret
self.url = url
def _build_header(self, query: dict, data: dict) -> dict:
accept = "application/json"
# 1. body MD5 加密
content_md5 = base64.b64encode(
hashlib.md5(
json.dumps(data).encode("utf-8")
).digest()
).decode()
content_type = "application/json"
gmt_format = '%a, %d %b %Y %H:%M:%S GMT'
date = datetime.datetime.utcnow().strftime(gmt_format)
signature_method = "HMAC-SHA256"
signature_nonce = str(random.randint(0, 65535))
header_string = f"POST\n{accept}\n{content_md5}\n{content_type}\n" \
f"{date}\n{signature_method}\n{signature_nonce}\n"
# 2. 计算 queryToSign
queries_str = []
for k, v in sorted(query.items(), key=lambda item: item[0]):
if isinstance(v, list):
for i in v:
queries_str.append(f"{k}={i}")
else:
queries_str.append(f"{k}={v}")
queries_string = '&'.join(queries_str)
# 3.计算 stringToSign
sign_string = header_string + queries_string
# 4.计算 HMAC-SHA256 + Base64
secret_bytes = self.access_secret.encode("utf-8")
# 5.计算签名
signature = base64.b64encode(
hmac.new(secret_bytes, sign_string.encode("utf-8"), hashlib.sha256).digest()
).decode()
res = {
"Content-Type": content_type,
"Content-MD5": content_md5,
"Date": date,
"Accept": accept,
"X-Langboat-Signature-Method": signature_method,
"X-Langboat-Signature-Nonce": signature_nonce,
"Authorization": f"{self.access_key}:{signature}"
}
return res
def inference(self, queries: dict, data: dict) -> (int, dict):
"""
服务调用: POST https://open.langboat.com/chat
:param queries: query 参数
:param data: request body 数据
:return: response status, response body to json
"""
headers = self._build_header(queries, data)
response = requests.post(url=self.url + "/chat",
headers=headers, params=queries, json=data)
return response.status_code, response.json()
if __name__ == '__main__':
_access_key = '<Your access_key>'
_access_secret = '<Your access_secret>'
client = LangboatOpenClient(
access_key=_access_key,
access_secret=_access_secret
)
# 孟子GPT
_queries = {}
_data = {
"model": "mengzi-lite",
"messages": [
{
"role": "user",
"content": "你知道牛顿吗"
}
],
"n": 1,
"max_tokens": 1024,
"user": ""
}
status_code, result = client.inference(_queries, _data)
print("response status:", status_code)
print("response json:", json.dumps(result, ensure_ascii=False, indent=2))

Go (>=1.14)#

package main
import (
"crypto/hmac"
"crypto/md5"
"crypto/sha256"
"encoding/base64"
"fmt"
"io/ioutil"
"log"
"math/rand"
"net/http"
"net/url"
"sort"
"strings"
"time"
)
func main() {
client := OpenClient{
baseURL: "https://open.langboat.com",
accessKey: "Your_Access_Key",
accessSecret: "Your_Access_Secret",
}
reqBody := `{"model":"mengzi-lite","messages":[{"role":"user","content":"你知道牛顿吗"}],"temperature":1,"top_p":0,"n":1,"stream":false,"max_tokens":1024,"user":""}`
resp := client.inference(reqBody)
response, ok := resp.(*http.Response)
if !ok {
log.Fatal("fail to convert response")
}
body, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal("fail to read response body")
}
log.Println(string(body))
}
type OpenClient struct {
baseURL string
accessKey string
accessSecret string
}
func (c *OpenClient) inference(body string) interface{} {
targetURL := c.baseURL + "/chat"
client := &http.Client{
Timeout: 60 * time.Second,
}
// 构造header
var (
payload = strings.NewReader(body)
date = time.Now().UTC().Format(http.TimeFormat)
nonce = fmt.Sprint(10000 + rand.Intn(89999))
)
// 签名
signParam := SignParam{
Body: body,
DateGMT: date,
Nonce: nonce,
}
contentMD5, signature := GenSignature(signParam, c.accessSecret)
// 设置header
headers := map[string]string{
"Authorization": c.accessKey + ":" + signature,
"Content-Type": "application/json",
"Accept": "application/json",
"Date": date,
"Content-MD5": contentMD5,
"x-langboat-signature-method": "HMAC-SHA256",
"x-langboat-signature-nonce": nonce,
}
req, _ := http.NewRequest("POST", targetURL, payload)
for k, v := range headers {
req.Header.Add(k, v)
}
resp, err := client.Do(req)
if err != nil {
log.Println(err.Error())
}
return resp
}
// SignParam 生成签名需要的参数
type SignParam struct {
Body string // body数据
Query string // 原始query
DateGMT string // GTM时间
Nonce string // 随机数
}
func getMD5(str string) []byte {
h := md5.New()
h.Write([]byte(str))
return h.Sum(nil)
}
func hmacSha256(data string, secret string) []byte {
h := hmac.New(sha256.New, []byte(secret))
h.Write([]byte(data))
return h.Sum(nil)
}
func resortQuery(src string) string {
queries, _ := url.ParseQuery(src)
keys := make([]string, 0)
for k := range queries {
keys = append(keys, k)
}
sort.Strings(keys)
newQuery := url.Values{}
for _, k := range keys {
for _, value := range queries[k] {
newQuery.Add(k, value)
}
}
return newQuery.Encode()
}
// GenSignature 生成签名
func GenSignature(src SignParam, accessSecret string) (string, string) {
// 计算body的md5值
md5str := getMD5(src.Body)
// base64后得到contentMD5
contentMD5 := base64.StdEncoding.EncodeToString(md5str)
// query解析,并按照字典序重新排列
query := resortQuery(src.Query)
query, _ = url.QueryUnescape(query)
// 需要做签名的字符串结构
stringToSign := `POST
application/json
%s
application/json
%s
HMAC-SHA256
%s
%s`
stringToSign = fmt.Sprintf(stringToSign, contentMD5, src.DateGMT, src.Nonce, query)
hmac256 := hmacSha256(stringToSign, accessSecret)
signature := base64.StdEncoding.EncodeToString(hmac256)
return contentMD5, signature
}

产品服务

关于我们

孟子社区

最新动态

加入澜舟

商务合作邮箱

公司地址

北京市海淀区北四环西路(街)52 号方正国际大厦 16 层 1603


gongan京公网安备 11010802035393号京ICP备 2021021087号

经营许可证编号:合字 B2-20220333

大模型备案号:Beijing-MengZiGPT-20231205


合作:

bd@langboat.com

地址:

北京市海淀区北四环西路(街)52 号方正国际大厦 16 层 1603

公众号:

ewm

support
business