最近公司有需要批量创作一些信息,所以我找找相关产品体验一下,比如阿里的通义千问、科大讯飞的讯飞星火等,下面主要说说讯飞星火的使用流程步骤及示例代码
全称讯飞星火认知大模型,是科大讯飞的产品
新一代认知智能大模型,拥有跨领域知识和语言理解能力,能够基于自然对话方式理解与执行任务
讯飞开放平台官网
https://www.xfyun.cn/
讯飞星火大模型申请
https://xinghuo.xfyun.cn/
讯飞开放平台开发web文档:
https://www.xfyun.cn/doc/spark/Web.html
ps:
当然申请之前你要注册好账号,创建应用,拿到appkey等api鉴权信息
这里就不过多介绍,自行进开发文档查阅。
讯飞星火大模型请求地址:
星火大模型API当前有V1.5和V2两个版本,两个版本独立计量tokens;
另两个版本的请求参数domain(详见下方请求参数)也需保持对应!
星火V1.5请求地址:
ws(s)://spark-api.xf-yun.com/v1.1/chat
星火V2请求地址:
ws(s)://spark-api.xf-yun.com/v2.1/chat
ps:
免费额度的只有星火V1.5有,所以下面以星火V1.5进行测试开发
来一张讯飞星火大模型申请成功进入后台的截图
话不多说进入步骤
打开开发文档
文档中心->星火认知大模型->开放能力->星火认知大模型Web文档
里面有一些详细的接口说明信息
最底部有一个
讯飞星火大模型各个语言调用demo,我这用php,所以下载一个php示例看看
demo中它用textalk/websocket扩展包的WebSocket\Client客户端连接讯飞星火大模型请求地址;
因为我用到hyperf 2.2框架,所以要改成hyperf适配的方式;
本身hyperf 2.2框架有自己的WebSocket协程客户端封装,所以只需要安装一下就ok了
安装命令:
composer require hyperf/websocket-client
创建控制器:
<?php
declare(strict_types=1);
namespace App\Controller;
use Hyperf\WebSocketClient\ClientFactory;
use Hyperf\DbConnection\Db;
use Hyperf\HttpServer\Annotation\AutoController;
/**
* @AutoController()
*/
class XfxhController extends BaseController
{
private $config = [
'appid' => 'xxx',
'apikey' => 'xxx',//密钥信息,在开放平台-控制台中获取:https://console.xfyun.cn/services/cbm
'apisecret' => 'xxx',
'addr' => 'ws://aichat.xf-yun.com/v1/chat',
];
/**
* @var ClientFactory
*/
protected $clientFactory;
public function __construct(ClientFactory $clientFactory)
{
$this->clientFactory = $clientFactory;
}
public function index()
{
$q = $this->request->input('q');
if (!isset($q)) { return ['code'=>400,'msg'=>"请输入提问,在url上以?q=xx的格式"]; };
if (empty($q)) { return ['code' => 400, 'msg' => "请输入信息,在url上以?q=xx的格式"];};
$authUrl = $this->assembleAuthUrl("GET",$this->config['addr'],$this->config['apikey'],$this->config['apisecret']);
// 创建ws连接对象
$client = $this->clientFactory->create($authUrl);
// 连接到 WebSocket 服务器
if ($client) {
// 发送数据到 WebSocket 服务器
// 数据格式
//$data = $this->getBody($Appid,"请你作为SEO撰写达人,写一篇有关".$q."的SEO文章,包括语言口语化,具有独特见解,原创性高。");
//五粮液高端系列酒亲身体验感受为题写一篇文章,要突出分别说出五粮液高端系列的普五、1618、交杯的体验感受,并且能说出竞品的区别
$data = $this->getBody($this->config['appid'],$q);
$client->push($data);
// 从 WebSocket 服务器接收数据
$answer = "";
while (true) {
$response = $client->recv();
//$resp = json_decode($response, true);
$resp = json_decode($response->data,true);
$code = $resp["header"]["code"];
echo "从服务器接收到的数据: " . $response;
if (0 == $code) {
$status = $resp["header"]["status"];
if ($status != 2) {
$content = $resp['payload']['choices']['text'][0]['content'];
$answer .= $content;
} else {
$content = $resp['payload']['choices']['text'][0]['content'];
$answer .= $content;
$total_tokens = $resp['payload']['usage']['text']['total_tokens'];
print("\n本次消耗token用量:\n");
print($total_tokens);
break;
}
} else {
echo "服务返回报错" . $response;
break;
}
}
print("\n返回结果为:\n");
print($answer);
return $answer;
} else {
return "无法连接到 WebSocket 服务器";
}
}
//构造参数体
function getBody($appid,$question){
$header = array(
"app_id" => $appid,
"uid" => "12345"
);
$parameter = array(
"chat" => array(
"domain" => "general",
"temperature" => 0.5,
"max_tokens" => 1024
)
);
$payload = array(
"message" => array(
"text" => array(
// 需要联系上下文时,要按照下面的方式上传历史对话
// array("role" => "user", "content" => "你是谁"),
// array("role" => "assistant", "content" => "....."),
// ...省略的历史对话
array("role" => "user", "content" => $question)
)
)
);
$json_string = json_encode(array(
"header" => $header,
"parameter" => $parameter,
"payload" => $payload
));
return $json_string;
}
//鉴权方法
function assembleAuthUrl($method, $addr, $apiKey, $apiSecret) {
if ($apiKey == "" && $apiSecret == "") { // 不鉴权
return $addr;
}
$ul = parse_url($addr); // 解析地址
if ($ul === false) { // 地址不对,也不鉴权
return $addr;
}
// // $date = date(DATE_RFC1123); // 获取当前时间并格式化为RFC1123格式的字符串
$timestamp = time();
$rfc1123_format = gmdate("D, d M Y H:i:s \G\M\T", $timestamp);
// $rfc1123_format = "Mon, 31 Jul 2023 08:24:03 GMT";
// 参与签名的字段 host, date, request-line
$signString = array("host: " . $ul["host"], "date: " . $rfc1123_format, $method . " " . $ul["path"] . " HTTP/1.1");
// 对签名字符串进行排序,确保顺序一致
// ksort($signString);
// 将签名字符串拼接成一个字符串
$sgin = implode("\n", $signString);
print( $sgin);
// 对签名字符串进行HMAC-SHA256加密,得到签名结果
$sha = hash_hmac('sha256', $sgin, $apiSecret,true);
print("signature_sha:\n");
print($sha);
$signature_sha_base64 = base64_encode($sha);
// 将API密钥、算法、头部信息和签名结果拼接成一个授权URL
$authUrl = "api_key=\"$apiKey\", algorithm=\"hmac-sha256\", headers=\"host date request-line\", signature=\"$signature_sha_base64\"";
// 对授权URL进行Base64编码,并添加到原始地址后面作为查询参数
$authAddr = $addr . '?' . http_build_query(array(
'host' => $ul['host'],
'date' => $rfc1123_format,
'authorization' => base64_encode($authUrl),
));
return $authAddr;
}
}
ps:
构造参数体、鉴权方法直接从官方的demo中复制过来,连接到WebSocket服务器基本一样,
主要修改的地方的就是发送数据到WebSocket服务器的send方法改成push;
运行测试一下,传参进来
http://127.0.0.1:9501/xfxh/index?q=你是谁
后话
对接进来,后面就可以进行其他场景的开发,比如根据关键词等自动生成相关信息,太多的话搞成定时任务方式等等。