Files
luban-lite/packages/third-party/llm_chat/ports/chat_port.c
刘可亮 6e36e8e296 v1.2.0
2025-04-23 17:54:31 +08:00

160 lines
5.0 KiB
C

/*
* Copyright (c) 2006-2025, RT-Thread Development Team
*
* SPDX-License-Identifier: MIT
*
* Change Logs:
* Date Author Notes
* 2025/02/01 Rbb666 Add license info
* 2025/02/03 Rbb666 Unified Adaptive Interface
* 2025/02/06 Rbb666 Add http stream support
*/
#include "llm.h"
#include "webclient.h"
#include <cJSON.h>
#define LLM_API_KEY LPKG_LLM_API_KEY
#define LLM_API_URL LPKG_LLM_DEEPSEEK_API_URL
#define LLM_MODEL_NAME LPKG_LLM_MODEL_NAME
#define WEB_SOCKET_BUF_SIZE LPKG_WEB_SORKET_BUFSZ
static char authHeader[128] = {0};
static char responseBuffer[WEB_SOCKET_BUF_SIZE] = {0};
static char contentBuffer[WEB_SOCKET_BUF_SIZE] = {0};
char *get_llm_answer(const char *inputText)
{
struct webclient_session *webSession = NULL;
char *allContent = NULL;
int bytesRead, responseStatus;
cJSON *responseRoot = NULL;
cJSON *requestRoot = NULL;
char *payload = NULL;
// Create web session
webSession = webclient_session_create(WEB_SOCKET_BUF_SIZE);
if (webSession == NULL)
{
rt_kprintf("Failed to create webclient session.\n");
goto cleanup;
}
// Create JSON payload
requestRoot = cJSON_CreateObject();
cJSON *model = cJSON_CreateString(LLM_MODEL_NAME);
cJSON *messages = cJSON_CreateArray();
cJSON *systemMessage = cJSON_CreateObject();
cJSON *userMessage = cJSON_CreateObject();
cJSON_AddItemToObject(requestRoot, "model", model);
cJSON_AddItemToObject(requestRoot, "messages", messages);
#ifdef LPKG_LLMCHAT_STREAM
cJSON_AddBoolToObject(requestRoot, "stream", RT_TRUE);
#else
cJSON_AddBoolToObject(requestRoot, "stream", RT_FALSE);
#endif
cJSON_AddItemToArray(messages, systemMessage);
cJSON_AddItemToArray(messages, userMessage);
cJSON_AddStringToObject(systemMessage, "role", "system");
cJSON_AddStringToObject(systemMessage, "content", "");
cJSON_AddStringToObject(userMessage, "role", "user");
cJSON_AddStringToObject(userMessage, "content", inputText);
payload = cJSON_PrintUnformatted(requestRoot);
if (payload == NULL)
{
rt_kprintf("Failed to create JSON payload.\n");
goto cleanup;
}
// Prepare authorization header
rt_snprintf(authHeader, sizeof(authHeader), "Authorization: Bearer %s\r\n", LLM_API_KEY);
// Add headers
webclient_header_fields_add(webSession, "Content-Type: application/json\r\n");
webclient_header_fields_add(webSession, authHeader);
webclient_header_fields_add(webSession, "Content-Length: %d\r\n", rt_strlen(payload));
LLM_DBG("HTTP Header: %s\n", webSession->header->buffer);
LLM_DBG("HTTP Payload: %s\n", payload);
// Send POST request
responseStatus = webclient_post(webSession, LLM_API_URL, payload, rt_strlen(payload));
if (responseStatus != 200)
{
rt_kprintf("Webclient POST request failed, response status: %d\n", responseStatus);
goto cleanup;
}
// Read and process response
while ((bytesRead = webclient_read(webSession, responseBuffer, WEB_SOCKET_BUF_SIZE)) > 0)
{
int inContent = 0;
for (int i = 0; i < bytesRead; i++)
{
if (inContent)
{
if (responseBuffer[i] == '"')
{
inContent = 0;
// Append content to allContent
char *oldAllContent = allContent;
size_t oldLen = oldAllContent ? rt_strlen(oldAllContent) : 0;
size_t newLen = rt_strlen(contentBuffer);
size_t totalLen = oldLen + newLen + 1;
char *newAllContent = (char *)web_malloc(totalLen);
if (newAllContent)
{
newAllContent[0] = '\0';
if (oldAllContent)
{
rt_strcpy(newAllContent, oldAllContent);
}
strcat(newAllContent, contentBuffer);
allContent = newAllContent;
rt_kprintf("%s", contentBuffer);
rt_free(oldAllContent);
}
else
{
rt_kprintf("Memory allocation failed, content truncated!\n");
}
contentBuffer[0] = '\0'; // Reset content buffer
}
else
{
strncat(contentBuffer, &responseBuffer[i], 1);
}
}
else if (responseBuffer[i] == '"' && i > 8 &&
rt_strncmp(&responseBuffer[i - 10], "\"content\":\"", 10) == 0)
{
inContent = 1;
}
}
}
rt_kprintf("\n");
cleanup:
// Cleanup resources
if (webSession)
webclient_close(webSession);
if (requestRoot)
cJSON_Delete(requestRoot);
if (responseRoot)
cJSON_Delete(responseRoot);
if (payload)
cJSON_free(payload);
return allContent;
}