2025-03-03 17:06:05 +01:00
// Written by retoor@molodetz.nl
2025-03-16 07:36:13 +01:00
// This code interacts with OpenAI's API to perform various tasks such as fetching models, sending chat messages, and processing responses.
2025-03-03 17:06:05 +01:00
// Uncommon imports include "http.h", "chat.h", and "http_curl.h". These may be internal or external libraries providing HTTP and JSON communication capabilities required to interact with APIs.
// MIT License
//
// Copyright (c) 2023
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
2025-01-05 22:59:51 +01:00
# ifndef R_OPENAI_H
# define R_OPENAI_H
2025-03-03 17:06:05 +01:00
2025-01-04 06:00:03 +01:00
# include "chat.h"
2025-01-27 18:57:21 +01:00
# include "http_curl.h"
2025-01-04 06:00:03 +01:00
# include <string.h>
# include <stdbool.h>
2025-03-03 13:51:57 +01:00
char * openai_fetch_models ( ) {
2025-03-03 17:06:05 +01:00
const char * api_url = " https://api.openai.com/v1/models " ;
2025-03-06 00:10:15 +01:00
return curl_get ( api_url ) ;
2025-01-04 06:00:03 +01:00
}
2025-03-03 13:51:57 +01:00
bool openai_system ( char * message_content ) {
2025-03-03 17:06:05 +01:00
chat_json ( " system " , message_content ) ;
2025-03-03 13:53:24 +01:00
return true ;
2025-01-04 06:00:03 +01:00
}
2025-03-03 17:06:05 +01:00
struct json_object * openai_process_chat_message ( const char * api_url , const char * json_data ) {
2025-03-03 13:51:57 +01:00
char * response = curl_post ( api_url , json_data ) ;
struct json_object * parsed_json = json_tokener_parse ( response ) ;
2025-01-04 08:40:31 +01:00
if ( ! parsed_json ) {
2025-03-16 07:36:13 +01:00
fprintf ( stderr , " Failed to parse JSON. \n %s \n " , response ) ;
2025-03-05 23:53:35 +01:00
return NULL ;
2025-03-03 13:51:57 +01:00
}
struct json_object * error_object ;
2025-03-03 17:06:05 +01:00
if ( json_object_object_get_ex ( parsed_json , " error " , & error_object ) ) {
2025-03-22 03:15:49 +01:00
2025-03-16 07:36:13 +01:00
char * all_messages = ( char * ) json_object_to_json_string ( message_array ) ;
2025-03-22 03:15:49 +01:00
2025-03-05 23:53:35 +01:00
fprintf ( stderr , " Messages: " ) ;
2025-03-16 07:36:13 +01:00
fwrite ( all_messages , strlen ( all_messages ) , 1 , stderr ) ;
2025-03-05 23:53:35 +01:00
fprintf ( stderr , " \n " ) ;
free ( all_messages ) ;
2025-03-22 03:15:49 +01:00
fprintf ( stderr , " %s \n " , json_object_to_json_string ( parsed_json ) ) ;
json_object_put ( parsed_json ) ;
2025-03-05 23:53:35 +01:00
messages_remove_last ( ) ;
2025-03-22 03:15:49 +01:00
2025-03-05 23:53:35 +01:00
messages_remove_last ( ) ;
2025-03-22 03:15:49 +01:00
2025-03-05 23:53:35 +01:00
return NULL ;
2025-01-04 06:00:03 +01:00
}
2025-03-03 13:51:57 +01:00
2025-01-27 19:06:59 +01:00
struct json_object * choices_array ;
2025-01-04 06:00:03 +01:00
if ( ! json_object_object_get_ex ( parsed_json , " choices " , & choices_array ) ) {
2025-03-16 07:36:13 +01:00
fprintf ( stderr , " Failed to get 'choices' array. \n %s \n " , response ) ;
2025-01-04 06:00:03 +01:00
json_object_put ( parsed_json ) ;
2025-03-05 23:53:35 +01:00
return NULL ;
2025-01-04 06:00:03 +01:00
}
2025-01-27 19:06:59 +01:00
struct json_object * first_choice = json_object_array_get_idx ( choices_array , 0 ) ;
2025-01-04 06:00:03 +01:00
if ( ! first_choice ) {
fprintf ( stderr , " Failed to get the first element of 'choices'. \n " ) ;
json_object_put ( parsed_json ) ;
2025-03-05 23:53:35 +01:00
return NULL ;
2025-01-04 06:00:03 +01:00
}
2025-03-03 08:32:41 +01:00
struct json_object * message_object ;
2025-01-04 06:00:03 +01:00
if ( ! json_object_object_get_ex ( first_choice , " message " , & message_object ) ) {
fprintf ( stderr , " Failed to get 'message' object. \n " ) ;
json_object_put ( parsed_json ) ;
2025-03-05 23:53:35 +01:00
return NULL ;
2025-01-04 06:00:03 +01:00
}
2025-03-03 08:07:17 +01:00
return message_object ;
}
2025-03-03 17:06:05 +01:00
char * openai_chat ( const char * user_role , const char * message_content ) {
2025-03-16 22:46:09 +01:00
if ( message_content = = NULL | | * message_content = = ' \0 ' | | * message_content = = ' \n ' ) {
return NULL ;
}
2025-03-03 17:06:05 +01:00
const char * api_url = " https://api.openai.com/v1/chat/completions " ;
2025-03-03 13:51:57 +01:00
char * json_data = chat_json ( user_role , message_content ) ;
2025-03-03 17:06:05 +01:00
struct json_object * message_object = openai_process_chat_message ( api_url , json_data ) ;
2025-03-20 16:38:10 +01:00
message_add_object ( message_object ) ;
2025-03-16 07:36:13 +01:00
if ( message_object = = NULL ) {
2025-03-05 23:53:35 +01:00
printf ( " ERROR + NULL IS SUCCESS \n " ) ;
2025-03-16 07:36:13 +01:00
return NULL ;
2025-03-05 23:53:35 +01:00
}
2025-03-03 08:32:41 +01:00
struct json_object * tool_calls ;
2025-03-03 08:07:17 +01:00
json_object_object_get_ex ( message_object , " tool_calls " , & tool_calls ) ;
if ( tool_calls ) {
2025-03-20 16:38:10 +01:00
// message_add_tool_call(message_object);
2025-03-03 17:06:05 +01:00
struct json_object * tool_call_results = tools_execute ( tool_calls ) ;
2025-03-03 13:51:57 +01:00
int results_count = json_object_array_length ( tool_call_results ) ;
for ( int i = 0 ; i < results_count ; i + + ) {
2025-03-03 17:06:05 +01:00
struct json_object * tool_call_result = json_object_array_get_idx ( tool_call_results , i ) ;
2025-03-03 08:32:41 +01:00
message_add_tool_call ( tool_call_result ) ;
2025-03-03 08:07:17 +01:00
}
2025-03-03 08:32:41 +01:00
char * tool_calls_result_str = chat_json ( NULL , NULL ) ;
2025-03-03 13:51:57 +01:00
message_object = openai_process_chat_message ( api_url , tool_calls_result_str ) ;
2025-03-16 07:36:13 +01:00
if ( message_object = = NULL ) {
return NULL ;
2025-03-05 23:53:35 +01:00
}
2025-03-20 17:00:13 +01:00
message_add_object ( message_object ) ;
//message_add_tool_call(message_object);
2025-03-03 08:07:17 +01:00
}
2025-03-03 17:06:05 +01:00
const char * content_str = json_object_get_string ( json_object_object_get ( message_object , " content " ) ) ;
2025-03-03 08:32:41 +01:00
return strdup ( content_str ) ;
2025-01-04 06:00:03 +01:00
}
2025-03-16 22:46:09 +01:00
# endif