前言
发现两个多月没写文章了,不过考试月也没啥好写的。
最近大模型这么火,正好有个项目用到,于是便水一篇教程吧。
此篇教程为 科大讯飞的星火大模型
部署教程,部署完成后即可与智能助手进行聊天。
这里是关于部署到服务器端,如果有其他需求可以查看官方文档。
大模型简介
大语言模型 (英语:large language model,LLM) 是一种语言模型,由具有许多参数(通常数十亿个权重或更多)的人工神经网络组成,使用自监督学习或半监督学习对大量未标记文本进行训练[1]。大型语言模型在2018年左右出现,并在各种任务中表现出色[2]。
尽管这个术语没有正式的定义,但它通常指的是参数数量在数十亿或更多数量级的深度学习模型[3]。大型语言模型是通用的模型,在广泛的任务中表现出色,而不是针对一项特定任务(例如情感分析、命名实体识别或数学推理)进行训练[2]。
尽管在预测句子中的下一个单词等简单任务上接受过训练,但发现具有足够训练和参数计数的神经语言模型可以捕获人类语言的大部分句法和语义。 此外大型语言模型展示了相当多的关于世界的常识,并且能够在训练期间“记住”大量事实[2]。
部署
API领取
首先前往科大讯飞的星火大模型官网 讯飞星火认知大模型-AI大语言模型-星火大模型-科大讯飞 (xfyun.cn)
进行注册,然后领取大模型的API
这里选择 API免费试用
,然后进入如下页面
选择第一个 个人免费包免费试用
。等到领取成功后,后台会有如下界面
这里的 APPID
、APISecret
、APIKey
就是接口信息,后面会用到。
Linux SDK 下载
进入上面页面后,点击 Linux SDK
右边的下载按钮。将会下载SDK包,感兴趣的也可以点击文档查看使用教程
下载完成后传到服务器,使用解压命令解压包
unzip Spark3.0_Linux_SDK_v1.1.zip
然后进入解压出来的包 Spark3.0_Linux_SDK_v1.1
, 里面应该包含如下文件
root@echofree:/opt# cd Spark3.0_Linux_SDK_v1.1/
root@echofree:/opt/Spark3.0_Linux_SDK_v1.1# ls
build include lib src
动态库配置
进入 lib
目录,里面会有一个相关的调用库
root@echofree:/opt/Spark3.0_Linux_SDK_v1.1# cd lib/
root@echofree:/opt/Spark3.0_Linux_SDK_v1.1/lib# ls
libSparkChain.so
这里为了方便点,直接采用暴力方法,将库文件 libSparkChain.so
复制到 /usr/lib
下
cp libSparkChain.so /usr/lib
API接口配置
进入 src
目录,会有一个 demo.cpp
文件,进入此文件,修改如下信息
int initSDK()
{
// 全局初始化
SparkChainConfig *config = SparkChainConfig::builder();
config->appID("appID") // 你的appid
->apiKey("apiKey") // 你的apikey
->apiSecret("apiSecret"); // 你的apisecret
// ->logLevel(0)
// ->logPath("./aikit.log");
int ret = SparkChain::init(config);
printf(RED "\ninit SparkChain result:%d" RESET,ret);
return ret;
}
将这里的 三个API配置信息改为自己的即可。
demo测试
配置完成后就要测试连接了,使用 GNU
编译套件进行编译,命令如下
g++ -Iinclude src/demo.cpp -o demo -lSparkChain -lstdc++ -lpthread
如果你会 Makefile
的话,也可以复制下面的进行编译
CC = g++
CFLAGS = -Iinclude
LIBS = -lSparkChain -lstdc++ -lpthread
SRC = src/server.cpp
OUTPUT = demo
all: $(OUTPUT)
$(OUTPUT): $(SRC)
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
clean:
rm -f $(OUTPUT)
如果一切正常,文件夹下会生成一个可执行文件 demo
root@echofree:/opt/Spark3.0_Linux_SDK_v1.1# ls
build demo files include lib src
运行看看
root@echofree:/opt/Spark3.0_Linux_SDK_v1.1# ./demo
######### llm Demo #########
init SparkChain result:0
######### 同步调用 #########
syncOutput: assistant:Hello
syncOutput: assistant:こんにちは
######### 异步调用 #########
0:assistant:Hello:myContext
2:assistant::myContext
tokens:1 + 5 = 6
0:assistant:こ:myContext
1:assistant:んに:myContext
1:assistant:ちは (:myContext
1:assistant:Konnichi:myContext
2:assistant:wa):myContext
tokens:12 + 10 = 22
很好,配置完成!
加点互动
下面就要给他加互动功能了,毕竟大模型不能进行交互聊天,那还要他做什么
修改 demo.cpp
文件,内容如下
记得修改下 API信息哦
#include "../include/sparkchain.h"
#include <iostream>
#include <string>
#include <atomic>
#include <unistd.h>
#include <regex>
#define GREEN "\033[32m"
#define YELLOW "\033[33m"
#define RED "\033[31m"
#define RESET "\033[0m"
using namespace SparkChain;
using namespace std;
// async status tag
static atomic_bool finish(false);
// result cache
string final_result = "";
class SparkCallbacks : public LLMCallbacks
{
void onLLMResult(LLMResult *result, void *usrContext)
{
int status = result->getStatus();
printf(GREEN "%d:%s:%s:%s \n" RESET, status, result->getRole(), result->getContent(), usrContext);
final_result += string(result->getContent());
if (status == 2)
{
printf(GREEN "tokens:%d + %d = %d\n" RESET, result->getCompletionTokens(), result->getPromptTokens(), result->getTotalTokens());
finish = true;
}
}
void onLLMEvent(LLMEvent *event, void *usrContext)
{
printf(YELLOW "onLLMEventCB\n eventID:%d eventMsg:%s\n" RESET, event->getEventID(), event->getEventMsg());
}
void onLLMError(LLMError *error, void *usrContext)
{
printf(RED "onLLMErrorCB\n errCode:%d errMsg:%s \n" RESET, error->getErrCode(), error->getErrMsg());
finish = true;
}
};
int initSDK()
{
// 全局初始化
SparkChainConfig *config = SparkChainConfig::builder();
config->appID("appID") // 你的appid
->apiKey("apiKey") // 你的apikey
->apiSecret("apiSecret"); // 你的apisecret
// ->logLevel(0)
// ->logPath("./aikit.log");
int ret = SparkChain::init(config);
printf(RED "\ninit SparkChain result:%d" RESET,ret);
return ret;
}
void syncLLMTest()
{
cout << "\n######### 同步调用 #########" << endl;
// 配置大模型参数
LLMConfig *llmConfig = LLMConfig::builder();
llmConfig->domain("generalv3");
llmConfig->url("ws(s)://spark-api.xf-yun.com/v3.1/chat");
Memory* window_memory = Memory::WindowMemory(5);
LLM *syncllm = LLM::create(llmConfig, window_memory);
// Memory* token_memory = Memory::TokenMemory(500);
// LLM *syncllm = LLM::create(llmConfig,token_memory);
int i = 0;
//const char* input = "";
while (1)
{
char input[256]; // 定义一个足够大的字符数组来接收用户输入
printf("请输入问题 (输入 'q' 退出):");
scanf("%s", input);
if (strcmp(input, "q") == 0) {
break; // 如果输入是 'q',则退出循环
}
// 同步请求
LLMSyncOutput *result = syncllm->run(input);
if (result->getErrCode() != 0)
{
printf(RED "\nsyncOutput: %d:%s\n\n" RESET, result->getErrCode(), result->getErrMsg());
continue;
}
else
{
printf(GREEN "\nsyncOutput: %s:%s\n" RESET, result->getRole(), result->getContent());
}
}
// 垃圾回收
if (syncllm != nullptr)
{
LLM::destroy(syncllm);
}
}
void uninitSDK()
{
// 全局逆初始化
SparkChain::unInit();
}
int main(int argc, char const *argv[])
{
cout << "\n######### llm Demo #########" << endl;
// 全局初始化
int ret = initSDK();
if (ret != 0)
{
cout << "initSDK failed:" << ret << endl;
return -1;
}
syncLLMTest(); // 同步调用
// 退出
uninitSDK();
return 0;
}
如果你仔细观察,会发现少了一部分代码。
星火大模型的接口调用给了两种方式,一种是同步,一种是异步
![](https://i-blog.csdnimg.cn/blog_migrate/f2f2c91f6bbc874713d32a072a396c98.png)
这里我用的是同步,所有文字都输出完,才会打印在终端。
正常的大模型,应该都是异步调用,即慢慢打印出来,这里留给读者自己修改了。
下面看下运行效果
root@echofree:/opt/Spark3.0_Linux_SDK_v1.1# ./demo
######### llm Demo #########
init SparkChain result:0
######### 同步调用 #########
请输入问题 (输入 'q' 退出):徐州天气怎么样
syncOutput: assistant:今天徐州市的天气是多云,气温在3℃到11℃之间,有点冷。东风4-5级,湿度为53%。空气质量良好,PM2.5指数为60。在这样的天气条件下,适宜旅游、钓鱼和户外运动,但要注意保暖。同时,感冒较易发生,请注意保持干净整洁的环境和清新流通的空气。
请输入问题 (输入 'q' 退出):你是什么
syncOutput: assistant:您好,我是科大讯飞研发的认知智能大模型,我的名字叫讯飞星火认知大模型。我可以和人类进行自然交流,解答问题,高效完成各领域认知智能需求。
请输入问题 (输入 'q' 退出):q
root@echofree:/opt/Spark3.0_Linux_SDK_v1.1#
效果还是不错的。
整点花活
既然一切都配置ok了,那肯定得进行应用开发了,这里来个小demo
这里是使用 Qt
开发的一个非常质朴的聊天界面,也就是开头所说的项目中正好用到大模型的地方。由于时间紧张,技术能力有限,就直接搬上去了。
具体原理就是使用 Linux的 socket
和 多线程
与界面进行通信。服务器端负责接收客户端的信息并进行回复。
后续
由于技术有限,并且考试月繁忙,等到有空闲时间了,再写个单独的交互界面。