《Linux操作系统编程详解》《笔试/面试常见算法:从基础到进阶》《Python干货分享》
🎬 艾莉丝的简介:
文章目录
- 1 ~> Ollama API 基础认知
- 1.1 核心能力与接口定位
- 1.2 通用约定
- 1.2.1 模型命名规则
- 1.2.2 时长单位
- 1.2.3 流式响应约定
- 2 ~> /api/chat 全量返回接口规范
- 2.1 接口基本信息
- 2.2 请求参数体系
- 2.2.1 必选参数
- 2.2.2 可选高级参数
- 2.3 响应报文结构
- 2.4 响应核心字段说明
- 3 ~> 环境验证与常见排障
- 3.1 curl 接口验证命令
- 3.2 常见故障排查
- 3.2.1 代理冲突问题
- 3.2.2 首次请求慢问题
- 4 ~> C++ 全量返回实现流程
- 4.1 实现总流程
- 4.2 模型有效性检测
- 4.3 请求参数构造
- 4.3.1 超参数提取
- 4.3.2 历史消息构建
- 4.4 请求体构建与序列化
- 4.5 HTTP 客户端配置与请求发送
- 4.6 响应反序列化与内容提取
- 5 ~> 单元测试与工程配置
- 5.1 测试用例编写
- 5.2 CMake 构建配置
- 6 ~> 扩展知识点
- 6.1 推理模型思考字段
- 6.2 结构化输出支持
- 结尾
1 ~> Ollama API 基础认知
1.1 核心能力与接口定位
- Ollama 是本地大模型部署与推理服务,通过标准化 REST API 封装屏蔽不同模型的参数差异,对外提供统一的调用入口。
- 聊天补全场景核心接口为
/api/chat,支持流式响应与全量响应两种模式,本次聚焦全量返回模式(stream: false)。
1.2 通用约定
1.2.1 模型命名规则
- 采用
模型名:标签格式,例如deepseek-r1:1.5b,标签用于标识具体版本与参数量。
1.2.2 时长单位
- 所有时间类字段统一以纳秒为单位返回。
1.2.3 流式响应约定
- 接口默认启用流式响应,逐块返回 JSON 对象;通过
stream: false可关闭流式,一次性返回完整响应对象。
2 ~> /api/chat 全量返回接口规范
2.1 接口基本信息
- 请求方法:
POST - 接口路径:
/api/chat - 默认服务地址:
http://127.0.0.1:11434 - Content-Type:
application/json
2.2 请求参数体系
2.2.1 必选参数
model:字符串类型,指定调用的模型名称,符合模型命名约定。messages:数组类型,存储对话历史消息,用于维持对话上下文记忆。- 单条消息对象字段:
role:消息角色,取值为system、user、assistant、tool。content:字符串类型,消息文本内容。images:可选,数组类型,多模态模型传入的图片列表。tool_calls:可选,数组类型,模型发起的工具调用请求列表。
- 单条消息对象字段:
2.2.2 可选高级参数
stream:布尔类型,控制是否启用流式响应,false为全量返回模式。format:字符串类型,指定响应返回格式,支持json或自定义 JSON Schema,用于实现结构化输出。options:JSON 对象,模型推理超参数,核心字段包括:temperature:浮点型,控制生成随机性,取值范围 0~1,值越高创造性越强。num_ctx:整型,上下文窗口大小,默认值 2048,对应其他平台的max_tokens语义。- 支持 Modelfile 中定义的其他模型参数。
keep_alive:字符串类型,控制模型在请求后保留在内存中的时长,默认 5 分钟。tools:数组类型,模型可调用的工具列表,JSON 格式,需模型支持。
2.3 响应报文结构
全量模式下返回单一 JSON 对象,标准结构如下:
{"model":"deepseek-r1:1.5b","created_at":"2026-08-28T04:56:59.195988466Z","message":{"role":"assistant","content":"\n\n您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-R1。如您有任何问题,我会尽我所能为您提供帮助。"},"done":true,"done_reason":"stop","total_duration":39751163910,"load_duration":1337544202,"prompt_eval_count":6,"prompt_eval_duration":1795779000,"eval_count":40,"eval_duration":35587041000}2.4 响应核心字段说明
model:本次响应使用的模型名称。created_at:响应生成时间戳,ISO 8601 格式。message:模型回复消息对象,包含role与content字段。done:布尔类型,标识响应是否完成,全量模式下恒为true。done_reason:结束原因,stop表示正常结束。total_duration:请求总耗时,单位纳秒。load_duration:模型加载耗时,单位纳秒。prompt_eval_count:输入 Prompt 的 Token 数量。prompt_eval_duration:输入 Prompt 推理耗时,单位纳秒。eval_count:输出回复的 Token 数量。eval_duration:输出生成耗时,单位纳秒。
3 ~> 环境验证与常见排障
3.1 curl 接口验证命令
标准全量返回验证请求命令:
curl-s-XPOST"http://127.0.0.1:11434/api/chat"\-H"Content-Type: application/json"\-d'{ "model": "deepseek-r1:1.5b", "stream": false, "messages": [ { "role": "user", "content": "你是谁?" } ], "options": { "temperature": 0.7, "num_ctx": 2048 } }'3.2 常见故障排查
3.2.1 代理冲突问题
- 现象:请求无响应、连接超时或失败。
- 成因:系统环境变量配置了 HTTP 代理,curl 默认继承代理配置,导致本地请求被代理转发。
- 排查步骤:
- 检查并关闭终端代理环境变量,执行
source ~/.bashrc重新加载环境配置。 - 检查 curl 配置文件
~/.curlrc,注释掉代理配置行。 - 重启终端后重新执行请求。
- 检查并关闭终端代理环境变量,执行
3.2.2 首次请求慢问题
- 现象:首次调用接口耗时显著高于后续调用。
- 成因:Ollama 需要将模型从磁盘加载到内存中,属于冷启动开销。
- 说明:属于正常现象,模型加载完成后后续请求速度显著提升;可通过
keep_alive参数延长模型驻留时间。
4 ~> C++ 全量返回实现流程
4.1 实现总流程
- 模型有效性检测
- 构造请求参数(温度、上下文窗口、历史消息)
- 构建并序列化 JSON 请求体
- 创建 HTTP 客户端并配置超时
- 发送 POST 请求
- 响应状态校验
- JSON 反序列化
- 提取模型回复内容
4.2 模型有效性检测
// 发送消息-全量返回std::stringOllamaLLMProvider::sendMessage(conststd::vector<Message>&messages,conststd::map<std::string,std::string>&requestParam){// 检查模型是否可用if(!isAvailable()){ERR("OllamaLLMProvider::sendMessage: model is not available");return"";}4.3 请求参数构造
4.3.1 超参数提取
从请求参数中提取温度与上下文窗口大小,未配置则使用默认值:
// 构造温度值和上下文Token数floattemperature=0.7f;intnumCtx=2048;if(requestParam.find("temperature")!=requestParam.end()){temperature=std::stof(requestParam.at("temperature"));}if(requestParam.find("max_tokens")!=requestParam.end()){numCtx=std::stoi(requestParam.at("max_tokens"));}4.3.2 历史消息构建
将内部消息结构转换为 JSON 数组格式:
// 构建历史消息数组Json::ValuemessageArray(Json::arrayValue);for(constauto&message:messages){Json::ValuemessageObject(Json::objectValue);messageObject["role"]=message._role;messageObject["content"]=message._content;messageArray.append(messageObject);}4.4 请求体构建与序列化
**注意:**Ollama 接口中上下文窗口参数字段为
num_ctx,而非通用的max_tokens。
// 构建options超参数对象Json::Valueoptions(Json::objectValue);options["temperature"]=temperature;options["num_ctx"]=numCtx;// 构建完整请求体Json::ValuerequestBody(Json::objectValue);requestBody["model"]=_modelName;requestBody["messages"]=messageArray;requestBody["options"]=options;requestBody["stream"]=false;// 序列化请求体为字符串Json::StreamWriterBuilder writerBuilder;std::string requestBodyStr=Json::writeString(writerBuilder,requestBody);4.5 HTTP 客户端配置与请求发送
// 创建HTTP客户端,配置超时时间httplib::Clientclient(_endpoint.c_str());client.set_connection_timeout(30,0);// 连接超时30秒client.set_read_timeout(60,0);// 读取超时60秒// 设置请求头httplib::Headers headers={{"Content-Type","application/json"}};// 发送POST请求autoresponse=client.Post("/api/chat",headers,requestBodyStr,"application/json");if(!response){ERR("OllamaLLMProvider::sendMessage: failed to send request, error: {}",to_string(response.error()));return"";}INFO("OllamaLLMProvider::sendMessage: response status: {}",response->status);INFO("OllamaLLMProvider::sendMessage: response body: {}",response->body);// 校验响应状态码if(response->status!=200){ERR("OllamaLLMProvider::sendMessage: failed to send request, status: {}",response->status);return"";}4.6 响应反序列化与内容提取
// 响应JSON反序列化Json::Value responseBody;Json::CharReaderBuilder reader;std::string errors;std::istringstreamresponseStream(response->body);if(!Json::parseFromStream(reader,responseStream,&responseBody,&errors)){ERR("OllamaLLMProvider::sendMessage: failed to parse response body, errors: {}",errors);return"";}// 提取模型回复内容std::string modelResponse;if(responseBody.isMember("message")&&responseBody["message"].isObject()&&responseBody["message"].isMember("content")){modelResponse=responseBody["message"]["content"].asString();INFO("OllamaLLMProvider::sendMessage: modelResponse: {}",modelResponse);returnmodelResponse;}// 响应格式异常处理ERR("OllamaLLMProvider::sendMessage: invalid response format");return"";}5 ~> 单元测试与工程配置
5.1 测试用例编写
基于 Google Test 框架的标准测试用例:
TEST(OllamaLLMProviderTest,sendMessage){autoprovider=std::make_shared<ai_chat_sdk::OllamaLLMProvider>();ASSERT_TRUE(provider!=nullptr);// 模型配置std::map<std::string,std::string>modelParam;modelParam["model_name"]="deepseek-r1:1.5b";modelParam["model_desc"]="本地部署deepseek-r1:1.5b模型,采用专家混合架构,专注于深度理解与推理";modelParam["endpoint"]="http://localhost:11434";provider->initModel(modelParam);ASSERT_TRUE(provider->isAvailable());// 请求参数配置std::map<std::string,std::string>requestParam={{"temperature","0.7"},{"max_tokens","2048"}};// 构造测试消息std::vector<ai_chat_sdk::Message>messages;messages.push_back({"user","你是谁?"});// 调用接口std::string fullData=provider->sendMessage(messages,requestParam);ASSERT_FALSE(fullData.empty());}5.2 CMake 构建配置
project(testLLM) # 设置C++标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 设置构建类型 set(CMAKE_BUILD_TYPE Debug) # 添加可执行文件 add_executable(testLLM testLLM.cpp ../sdk/src/util/myLog.cpp ../sdk/src/DeepSeekProvider.cpp ../sdk/src/ChatGPTProvider.cpp ../sdk/src/GeminiProvider.cpp ../sdk/src/OllamaLLMProvider.cpp ) # 设置输出目录 set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}) # 添加头文件搜索路径 include_directories(${CMAKE_PROJECT_INCLUDE_DIR}/../sdk/include) # 依赖库配置 find_package(OpenSSL REQUIRED) include_directories(${OPENSSL_INCLUDE_DIR}) # 编译宏定义 target_compile_definitions(testLLM PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT) # 链接依赖库 target_link_libraries(testLLM jsoncpp fmt spdlog gtest OpenSSL::SSL OpenSSL::Crypto )6 ~> 扩展知识点
6.1 推理模型思考字段
- 部分推理增强模型(如 DeepSeek-R1)会在回复内容中包含 `` 标签,内部存储模型推理思考过程。
- SDK 默认直接返回完整内容,思考字段的解析与过滤由上层业务自行处理。
6.2 结构化输出支持
- 通过
format参数传入 JSON Schema,可强制模型输出符合指定结构的 JSON 数据。 - 适用于需要固定格式返回的业务场景,如分类、信息提取、结构化生成等。
结尾
uu们,本文的内容到这里就全部结束了,艾莉丝在这里再次感谢您的阅读!
|
结语:希望对学习Linux相关内容的uu有所帮助,不要忘记给博主“一键四连”哦!
往期回顾:
【AI大模型接入SDK】Ollama大模型接入架构对比与实现
🗡博主在这里放了一只小狗,大家看完了摸摸小狗放松一下吧!🗡 ૮₍ ˶ ˊ ᴥ ˋ˶₎ა