llm-proxy / client.c
trung.le
feat: add C++ client and refresh client features
57ce88d
Raw
History Blame Contribute Delete
6.77 kB
/*
* LLM Proxy Client - C Version (Windows Native using WinINet)
* Compile: gcc -o llm_client client.c -lwininet
* Usage: llm_client.exe
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <wininet.h>
#define MAX_PROMPT_SIZE 4096
#define MAX_RESPONSE_SIZE 65536
typedef struct {
const char *name;
const char *id;
} LLMModel;
static const LLMModel MODELS[] = {
{"Laguna S 2.1 (Free)", "poolside/laguna-s-2.1:free"},
{"Gemini 3.6 Flash (Paid)", "google/gemini-3.6-flash"},
{"Claude Opus 5 (Paid)", "anthropic/claude-opus-5"},
{"Claude Fable 5 (Paid)", "anthropic/claude-fable-5"},
{"GPT-5.6 Sol (Paid)", "openai/gpt-5.6-sol"},
{"GPT-5.6 Luna (Paid)", "openai/gpt-5.6-luna"},
{"Nemotron 3 Ultra (Free)", "nvidia/nemotron-3-ultra-550b-a55b:free"}
};
static const int MODEL_COUNT = sizeof(MODELS) / sizeof(MODELS[0]);
char* ask_llm(const char *prompt, const LLMModel *model) {
HINTERNET hInternet = NULL, hConnect = NULL, hRequest = NULL;
char *response = NULL;
DWORD bytesRead = 0;
DWORD totalSize = 0;
char headers[512];
response = (char*)malloc(MAX_RESPONSE_SIZE);
if (!response) return _strdup("Error: Memory allocation failed");
memset(response, 0, MAX_RESPONSE_SIZE);
/* Initialize WinINet */
hInternet = InternetOpenA("LLM-Proxy-Client/1.0",
INTERNET_OPEN_TYPE_PRECONFIG,
NULL, NULL, 0);
if (!hInternet) {
free(response);
return _strdup("Error: Failed to open Internet session");
}
/* Connect to server */
hConnect = InternetConnectA(hInternet,
"ttl0110-llm-proxy.hf.space",
INTERNET_DEFAULT_HTTPS_PORT,
NULL, NULL,
INTERNET_SERVICE_HTTP,
0, 0);
if (!hConnect) {
InternetCloseHandle(hInternet);
free(response);
return _strdup("Error: Failed to connect to server");
}
/* Create request */
hRequest = HttpOpenRequestA(hConnect, "POST", "/ask",
NULL, NULL, NULL,
INTERNET_FLAG_SECURE | INTERNET_FLAG_RELOAD,
0);
if (!hRequest) {
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
free(response);
return _strdup("Error: Failed to create request");
}
/* Build headers */
snprintf(headers, sizeof(headers),
"Content-Type: text/plain\r\nX-Model: %s",
model->id);
/* Send request */
DWORD promptLen = (DWORD)strlen(prompt);
if (!HttpSendRequestA(hRequest, headers, (DWORD)strlen(headers),
(LPVOID)prompt, promptLen)) {
DWORD err = GetLastError();
char errMsg[128];
snprintf(errMsg, sizeof(errMsg), "Error: Failed to send request (code: %lu)", err);
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
free(response);
return _strdup(errMsg);
}
/* Read response data */
char buffer[4096];
while (InternetReadFile(hRequest, buffer, sizeof(buffer) - 1, &bytesRead) && bytesRead > 0) {
if (totalSize + bytesRead < MAX_RESPONSE_SIZE - 1) {
memcpy(response + totalSize, buffer, bytesRead);
totalSize += bytesRead;
}
}
response[totalSize] = '\0';
/* Cleanup */
InternetCloseHandle(hRequest);
InternetCloseHandle(hConnect);
InternetCloseHandle(hInternet);
return response;
}
void clear_input_buffer(void) {
int c;
while ((c = getchar()) != '\n' && c != EOF);
}
int main(void) {
char prompt[MAX_PROMPT_SIZE];
char prompt_prefix[MAX_PROMPT_SIZE] = {0};
int choice = 0;
/* Set console to UTF-8 */
SetConsoleOutputCP(CP_UTF8);
SetConsoleCP(CP_UTF8);
printf("=== C LLM Assistant (HuggingFace Proxy) ===\n\n");
/* Model Selection */
printf("Chon Model LLM:\n");
for (int i = 0; i < MODEL_COUNT; i++) {
printf("%d. %s\n", i + 1, MODELS[i].name);
}
while (choice < 1 || choice > MODEL_COUNT) {
printf("Nhap lua chon (1-%d): ", MODEL_COUNT);
if (scanf("%d", &choice) != 1) {
clear_input_buffer();
choice = 0;
}
}
clear_input_buffer();
const LLMModel *selected_model = &MODELS[choice - 1];
printf("Ban da chon: %s\n\n", selected_model->name);
printf("Nhap prompt prefix (bo trong neu khong dung): ");
if (fgets(prompt_prefix, sizeof(prompt_prefix), stdin) != NULL) {
prompt_prefix[strcspn(prompt_prefix, "\r\n")] = '\0';
}
printf("Huong dan: Nhap prompt cua ban. Nhap dong trong de gui.\n");
printf("Nhap 'EXIT' de thoat.\n");
while (1) {
printf("\nBan [%s]:\n", selected_model->name);
char full_prompt[MAX_PROMPT_SIZE] = {0};
size_t total_len = 0;
while (1) {
if (fgets(prompt, sizeof(prompt), stdin) == NULL) {
break;
}
/* Check for EXIT command */
if (_strnicmp(prompt, "EXIT", 4) == 0 && (prompt[4] == '\n' || prompt[4] == '\0')) {
printf("Tam biet!\n");
return 0;
}
/* Empty line means submit */
if (prompt[0] == '\n') {
break;
}
size_t line_len = strlen(prompt);
if (total_len + line_len < MAX_PROMPT_SIZE - 1) {
strcat(full_prompt, prompt);
total_len += line_len;
}
}
if (total_len == 0) {
printf("Prompt trong, vui long nhap lai.\n");
continue;
}
/* Remove trailing newline */
if (full_prompt[total_len - 1] == '\n') {
full_prompt[total_len - 1] = '\0';
}
char request_prompt[MAX_PROMPT_SIZE] = {0};
if (prompt_prefix[0] != '\0') {
int written = snprintf(request_prompt, sizeof(request_prompt), "%s\n\n%s",
prompt_prefix, full_prompt);
if (written < 0 || written >= (int)sizeof(request_prompt)) {
printf("Prompt va prefix qua dai, vui long nhap lai.\n");
continue;
}
} else {
strcpy(request_prompt, full_prompt);
}
printf("Thinking...\n");
char *response = ask_llm(request_prompt, selected_model);
printf("\n[LLM]: %s\n", response);
printf("-------------------------------------------\n");
free(response);
}
return 0;
}