/* * Copyright (c) 2025 Aldrik Ramaekers * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #define _CRT_SECURE_NO_WARNINGS #include #include #include #define CPPHTTPLIB_OPENSSL_SUPPORT #include "httplib.h" #include "strops.hpp" #include "logger.hpp" #include "importer.hpp" #define QUERY_BUFFER_SIZE 1000000 char* query_buffer = 0; static bool _DeepSeek_query_with_file(char* query, size_t query_length, char* file_id, char** response) { (void)file_id; (void)query_length; assert(query_buffer); const char *api_key = administration::get_ai_service().api_key_public; httplib::SSLClient cli("api.deepseek.com"); //cli.enable_server_certificate_verification(false); //char* query_escaped = strops::prep_str_for_json(query, query_length); //free(query); // TODO why?? size_t file_size = strlen(query_buffer); sprintf(query_buffer + file_size, "%s", query); char* query_escaped = strops::prep_str_for_json(query_buffer, strlen(query_buffer)); size_t body_size = file_size + QUERY_BUFFER_SIZE; char* body = (char*)malloc(body_size); strops::format(body, body_size, "{\"model\":\"deepseek-reasoner\", \"messages\": [ { \"role\": \"user\", \"content\": \"%s\" } ] }", query_escaped); httplib::Headers headers; headers.insert(std::make_pair("Authorization", std::string("Bearer ") + api_key)); headers.insert(std::make_pair("Content-Type", "application/json")); headers.insert(std::make_pair("Accept", "application/json")); httplib::Result res = cli.Post("/chat/completions", headers, body, "application/json"); free(body); if (!res || res->status != 200) { logger::error("ERROR Failed to query API."); logger::error(res->body.c_str()); return 0; } char* response_body = (char*)res->body.c_str(); *response = (char*)malloc(100000); memset(*response, 0, 100000); strncpy(*response, response_body, 100000); strops::get_json_value(*response, "content", *response, 100000); *response = strops::unprep_str_from_json(*response); return 1; } static bool _DeepSeek_upload_file(char* file_path, char* file_id, size_t file_id_len) { (void)file_id; (void)file_id_len; const char *filename = strops::get_filename(file_path); FILE* orig_file = fopen(file_path, "r"); if (orig_file == NULL) { logger::error("ERROR: file to upload could not be opened."); return 0; } fseek(orig_file, 0L, SEEK_END); long sz = ftell(orig_file); fseek(orig_file, 0, SEEK_SET); size_t buffer_size = sz + QUERY_BUFFER_SIZE; char* file_content_buffer = (char*)malloc(buffer_size); memset(file_content_buffer, 0, buffer_size); query_buffer = file_content_buffer; file_content_buffer += sprintf(file_content_buffer, "[file name]: %s\n", filename); file_content_buffer += sprintf(file_content_buffer, "[file content begin]\n"); fread(file_content_buffer, sz, 1, orig_file); file_content_buffer += sz; for (int i = 0; i < file_content_buffer-query_buffer; i++) if (query_buffer[i] <= 0x1f) query_buffer[i] = ' '; file_content_buffer += sprintf(file_content_buffer, "\n[file content end]\n"); file_content_buffer[0] = 0; fclose(orig_file); return 1; } importer::ai_provider_impl _deepseek_api_provider = { "DeekSeek", _DeepSeek_upload_file, _DeepSeek_query_with_file, };