Prompt Workbench Core 1.0.0
A C library for prompt testing and evaluation with OpenAI-compatible APIs (Educational Use Only)
Loading...
Searching...
No Matches
api-client.c
Go to the documentation of this file.
1/*
2 * Prompt Workbench Core - API Client Implementation
3 * Copyright (c) 2025 nnlazaro
4 *
5 * This file is part of Prompt Workbench Core, licensed under the
6 * Educational and Non-Commercial Use License.
7 * See LICENSE file for details.
8 *
9 * FOR EDUCATIONAL USE ONLY - NOT FOR PRODUCTION OR COMMERCIAL USE
10 */
11
12#include "api-client.h"
13#include <curl/curl.h>
14#include <cjson/cJSON.h>
15#include <stdlib.h>
16#include <string.h>
17#include <stdio.h>
18
20 char *memory;
21 size_t size;
22};
23
24static size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp) {
25 size_t realsize = size * nmemb;
26 struct MemoryChunk *mem = (struct MemoryChunk *)userp;
27
28 char *ptr = realloc(mem->memory, mem->size + realsize + 1);
29 if (!ptr) {
30 return 0;
31 }
32
33 mem->memory = ptr;
34 memcpy(&(mem->memory[mem->size]), contents, realsize);
35 mem->size += realsize;
36 mem->memory[mem->size] = 0;
37
38 return realsize;
39}
40
41char* api_ask(const char* api_endpoint,
42 const char* api_key,
43 const char* model,
44 const char* system_prompt,
45 const char* user_prompt) {
46
47 if (!api_endpoint || !api_key || !model || !system_prompt || !user_prompt) {
48 return NULL;
49 }
50
51 CURL *curl;
52 CURLcode res;
53 struct MemoryChunk chunk = {0};
54 struct curl_slist *headers = NULL;
55 char auth_header[512];
56 char *json_payload = NULL;
57 char *result = NULL;
58
59 // Build JSON request payload
60 cJSON *root = cJSON_CreateObject();
61 cJSON *messages = cJSON_CreateArray();
62 cJSON *system_msg = cJSON_CreateObject();
63 cJSON *user_msg = cJSON_CreateObject();
64
65 cJSON_AddStringToObject(root, "model", model);
66
67 cJSON_AddStringToObject(system_msg, "role", "system");
68 cJSON_AddStringToObject(system_msg, "content", system_prompt);
69 cJSON_AddItemToArray(messages, system_msg);
70
71 cJSON_AddStringToObject(user_msg, "role", "user");
72 cJSON_AddStringToObject(user_msg, "content", user_prompt);
73 cJSON_AddItemToArray(messages, user_msg);
74
75 cJSON_AddItemToObject(root, "messages", messages);
76
77 json_payload = cJSON_PrintUnformatted(root);
78 cJSON_Delete(root);
79
80 if (!json_payload) {
81 return NULL;
82 }
83
84 // Initialize response buffer
85 chunk.memory = malloc(1);
86 chunk.size = 0;
87
88 // Initialize curl
89 curl_global_init(CURL_GLOBAL_DEFAULT);
90 curl = curl_easy_init();
91
92 if (!curl) {
93 free(chunk.memory);
94 free(json_payload);
95 curl_global_cleanup();
96 return NULL;
97 }
98
99 // Set headers
100 headers = curl_slist_append(headers, "Content-Type: application/json");
101 snprintf(auth_header, sizeof(auth_header), "Authorization: Bearer %s", api_key);
102 headers = curl_slist_append(headers, auth_header);
103
104 // Configure curl
105 curl_easy_setopt(curl, CURLOPT_URL, api_endpoint);
106 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
107 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_payload);
108 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
109 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
110 curl_easy_setopt(curl, CURLOPT_USERAGENT, "prompt-workbench-core/1.0");
111 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
112 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L);
113
114 // Perform the request
115 res = curl_easy_perform(curl);
116
117 // Cleanup
118 curl_slist_free_all(headers);
119 curl_easy_cleanup(curl);
120 curl_global_cleanup();
121 free(json_payload);
122
123 if (res != CURLE_OK) {
124 free(chunk.memory);
125 return NULL;
126 }
127
128 // Parse JSON response and extract choices[0].message.content
129 cJSON *response_json = cJSON_Parse(chunk.memory);
130 free(chunk.memory);
131
132 if (!response_json) {
133 return NULL;
134 }
135
136 cJSON *choices = cJSON_GetObjectItem(response_json, "choices");
137 if (!choices || !cJSON_IsArray(choices) || cJSON_GetArraySize(choices) == 0) {
138 cJSON_Delete(response_json);
139 return NULL;
140 }
141
142 cJSON *first_choice = cJSON_GetArrayItem(choices, 0);
143 if (!first_choice) {
144 cJSON_Delete(response_json);
145 return NULL;
146 }
147
148 cJSON *message = cJSON_GetObjectItem(first_choice, "message");
149 if (!message) {
150 cJSON_Delete(response_json);
151 return NULL;
152 }
153
154 cJSON *content = cJSON_GetObjectItem(message, "content");
155 if (!content || !cJSON_IsString(content)) {
156 cJSON_Delete(response_json);
157 return NULL;
158 }
159
160 // Duplicate the content string before deleting JSON
161 result = strdup(content->valuestring);
162 cJSON_Delete(response_json);
163
164 return result;
165}
166
167void api_ask_free(char* response) {
168 if (response) {
169 free(response);
170 }
171}
static size_t write_callback(void *contents, size_t size, size_t nmemb, void *userp)
Definition api-client.c:24
char * api_ask(const char *api_endpoint, const char *api_key, const char *model, const char *system_prompt, const char *user_prompt)
Definition api-client.c:41
void api_ask_free(char *response)
Free a response string returned by API functions.
Definition api-client.c:167
size_t size
Definition api-client.c:21
char * memory
Definition api-client.c:20