| |
| |
| |
| |
| |
|
|
| #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); |
|
|
| |
| 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"); |
| } |
|
|
| |
| 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"); |
| } |
|
|
| |
| 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"); |
| } |
|
|
| |
| snprintf(headers, sizeof(headers), |
| "Content-Type: text/plain\r\nX-Model: %s", |
| model->id); |
|
|
| |
| 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); |
| } |
|
|
| |
| 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'; |
|
|
| |
| 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; |
|
|
| |
| SetConsoleOutputCP(CP_UTF8); |
| SetConsoleCP(CP_UTF8); |
|
|
| printf("=== C LLM Assistant (HuggingFace Proxy) ===\n\n"); |
|
|
| |
| 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; |
| } |
|
|
| |
| if (_strnicmp(prompt, "EXIT", 4) == 0 && (prompt[4] == '\n' || prompt[4] == '\0')) { |
| printf("Tam biet!\n"); |
| return 0; |
| } |
|
|
| |
| 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; |
| } |
|
|
| |
| 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; |
| } |
|
|