This commit is contained in:
parent
18c9199b79
commit
2e3a61d756
5 changed files with 46 additions and 569 deletions
537
api.json
537
api.json
|
@ -1,537 +0,0 @@
|
||||||
openapi: 3.0.0
|
|
||||||
info:
|
|
||||||
title: General Bots API
|
|
||||||
description: API for managing files, documents, groups, conversations, and more.
|
|
||||||
version: 1.0.0
|
|
||||||
servers:
|
|
||||||
- url: https://api.generalbots.com/v1
|
|
||||||
description: Production server
|
|
||||||
paths:
|
|
||||||
/files/upload:
|
|
||||||
post:
|
|
||||||
summary: Upload a file
|
|
||||||
operationId: uploadFile
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
multipart/form-data:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
file:
|
|
||||||
type: string
|
|
||||||
format: binary
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: File uploaded successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
fileId:
|
|
||||||
type: string
|
|
||||||
url:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
/files/download:
|
|
||||||
post:
|
|
||||||
summary: Download a file
|
|
||||||
operationId: downloadFile
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
fileId:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: File downloaded successfully
|
|
||||||
content:
|
|
||||||
application/octet-stream:
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
format: binary
|
|
||||||
|
|
||||||
/files/copy:
|
|
||||||
post:
|
|
||||||
summary: Copy a file
|
|
||||||
operationId: copyFile
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
sourcePath:
|
|
||||||
type: string
|
|
||||||
destinationPath:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: File copied successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
message:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
/files/move:
|
|
||||||
post:
|
|
||||||
summary: Move a file
|
|
||||||
operationId: moveFile
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
sourcePath:
|
|
||||||
type: string
|
|
||||||
destinationPath:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: File moved successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
message:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
/files/delete:
|
|
||||||
post:
|
|
||||||
summary: Delete a file
|
|
||||||
operationId: deleteFile
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
fileId:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: File deleted successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
message:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
/files/getContents:
|
|
||||||
post:
|
|
||||||
summary: Get file contents
|
|
||||||
operationId: getFileContents
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
fileId:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: File contents retrieved successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
contents:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
/files/save:
|
|
||||||
post:
|
|
||||||
summary: Save a file
|
|
||||||
operationId: saveFile
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
fileId:
|
|
||||||
type: string
|
|
||||||
contents:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: File saved successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
message:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
/files/createFolder:
|
|
||||||
post:
|
|
||||||
summary: Create a folder
|
|
||||||
operationId: createFolder
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
folderName:
|
|
||||||
type: string
|
|
||||||
parentFolderId:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Folder created successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
folderId:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
/files/shareFolder:
|
|
||||||
post:
|
|
||||||
summary: Share a folder
|
|
||||||
operationId: shareFolder
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
folderId:
|
|
||||||
type: string
|
|
||||||
userIds:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Folder shared successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
message:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
/files/dirFolder:
|
|
||||||
post:
|
|
||||||
summary: List folder contents
|
|
||||||
operationId: dirFolder
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
folderId:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Folder contents retrieved successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
size:
|
|
||||||
type: integer
|
|
||||||
|
|
||||||
/files/list:
|
|
||||||
post:
|
|
||||||
summary: List files
|
|
||||||
operationId: getFiles
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
folderId:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Files listed successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
size:
|
|
||||||
type: integer
|
|
||||||
|
|
||||||
/files/search:
|
|
||||||
post:
|
|
||||||
summary: Search files
|
|
||||||
operationId: searchFiles
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
query:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Files searched successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
size:
|
|
||||||
type: integer
|
|
||||||
|
|
||||||
/files/recent:
|
|
||||||
post:
|
|
||||||
summary: Get recent files
|
|
||||||
operationId: getRecentFiles
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Recent files retrieved successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
size:
|
|
||||||
type: integer
|
|
||||||
|
|
||||||
/files/favorite:
|
|
||||||
post:
|
|
||||||
summary: Toggle favorite status of a file
|
|
||||||
operationId: toggleFavorite
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
fileId:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Favorite status toggled successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
isFavorite:
|
|
||||||
type: boolean
|
|
||||||
|
|
||||||
/files/versions:
|
|
||||||
post:
|
|
||||||
summary: Get file versions
|
|
||||||
operationId: getFileVersions
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
fileId:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: File versions retrieved successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
versionId:
|
|
||||||
type: string
|
|
||||||
timestamp:
|
|
||||||
type: string
|
|
||||||
size:
|
|
||||||
type: integer
|
|
||||||
|
|
||||||
/files/restore:
|
|
||||||
post:
|
|
||||||
summary: Restore a file version
|
|
||||||
operationId: restoreFileVersion
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
fileId:
|
|
||||||
type: string
|
|
||||||
versionId:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: File version restored successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
message:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
/files/permissions:
|
|
||||||
post:
|
|
||||||
summary: Set file permissions
|
|
||||||
operationId: setFilePermissions
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
fileId:
|
|
||||||
type: string
|
|
||||||
permissions:
|
|
||||||
type: object
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: File permissions updated successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
message:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
/files/quota:
|
|
||||||
get:
|
|
||||||
summary: Get storage quota
|
|
||||||
operationId: getStorageQuota
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Storage quota retrieved successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
used:
|
|
||||||
type: integer
|
|
||||||
total:
|
|
||||||
type: integer
|
|
||||||
|
|
||||||
/files/shared:
|
|
||||||
get:
|
|
||||||
summary: Get shared files
|
|
||||||
operationId: getSharedFiles
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Shared files retrieved successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
type: string
|
|
||||||
size:
|
|
||||||
type: integer
|
|
||||||
|
|
||||||
/files/sync/status:
|
|
||||||
get:
|
|
||||||
summary: Get sync status
|
|
||||||
operationId: getSyncStatus
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Sync status retrieved successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
status:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
/files/sync/start:
|
|
||||||
post:
|
|
||||||
summary: Start sync
|
|
||||||
operationId: startSync
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Sync started successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
message:
|
|
||||||
type: string
|
|
||||||
|
|
||||||
/files/sync/stop:
|
|
||||||
post:
|
|
||||||
summary: Stop sync
|
|
||||||
operationId: stopSync
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: Sync stopped successfully
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
message:
|
|
||||||
type: string
|
|
23
src/main.rs
23
src/main.rs
|
@ -1,7 +1,6 @@
|
||||||
|
use actix_web::middleware::Logger;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use actix_cors::Cors;
|
|
||||||
use actix_web::http::header;
|
|
||||||
use actix_web::{web, App, HttpServer};
|
use actix_web::{web, App, HttpServer};
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
use services::state::*;
|
use services::state::*;
|
||||||
|
@ -11,6 +10,7 @@ use sqlx::PgPool;
|
||||||
use crate::services::automation::AutomationService;
|
use crate::services::automation::AutomationService;
|
||||||
use crate::services::email::{get_emails, list_emails, save_click, send_email};
|
use crate::services::email::{get_emails, list_emails, save_click, send_email};
|
||||||
use crate::services::llm::{chat, chat_stream};
|
use crate::services::llm::{chat, chat_stream};
|
||||||
|
use crate::services::llm_local::chat_completions_local;
|
||||||
use crate::services::llm_provider::chat_completions;
|
use crate::services::llm_provider::chat_completions;
|
||||||
use crate::services::web_automation::{initialize_browser_pool, BrowserPool};
|
use crate::services::web_automation::{initialize_browser_pool, BrowserPool};
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ async fn main() -> std::io::Result<()> {
|
||||||
"/usr/bin/brave-browser-beta".to_string(),
|
"/usr/bin/brave-browser-beta".to_string(),
|
||||||
));
|
));
|
||||||
|
|
||||||
#[cfg(feature = "local_llm")]
|
#[cfg(feature = "default")]
|
||||||
{
|
{
|
||||||
use crate::services::llm_local::ensure_llama_server_running;
|
use crate::services::llm_local::ensure_llama_server_running;
|
||||||
|
|
||||||
|
@ -67,15 +67,17 @@ async fn main() -> std::io::Result<()> {
|
||||||
|
|
||||||
// Start HTTP server
|
// Start HTTP server
|
||||||
HttpServer::new(move || {
|
HttpServer::new(move || {
|
||||||
let cors = Cors::default()
|
// let cors = Cors::default()
|
||||||
.send_wildcard()
|
// .send_wildcard()
|
||||||
.allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
|
// .allowed_methods(vec!["GET", "POST", "PUT", "DELETE"])
|
||||||
.allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
|
// .allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
|
||||||
.allowed_header(header::CONTENT_TYPE)
|
// .allowed_header(header::CONTENT_TYPE)
|
||||||
.max_age(3600);
|
// .max_age(3600);
|
||||||
|
//.wrap(cors)
|
||||||
|
|
||||||
App::new()
|
App::new()
|
||||||
.wrap(cors)
|
.wrap(Logger::default())
|
||||||
|
.wrap(Logger::new("%a %{User-Agent}i"))
|
||||||
.app_data(app_state.clone())
|
.app_data(app_state.clone())
|
||||||
.service(upload_file)
|
.service(upload_file)
|
||||||
.service(list_file)
|
.service(list_file)
|
||||||
|
@ -85,6 +87,7 @@ async fn main() -> std::io::Result<()> {
|
||||||
.service(send_email)
|
.service(send_email)
|
||||||
.service(chat_stream)
|
.service(chat_stream)
|
||||||
.service(chat_completions)
|
.service(chat_completions)
|
||||||
|
.service(chat_completions_local)
|
||||||
.service(chat)
|
.service(chat)
|
||||||
})
|
})
|
||||||
.bind((config.server.host.clone(), config.server.port))?
|
.bind((config.server.host.clone(), config.server.port))?
|
||||||
|
|
|
@ -27,16 +27,16 @@ CPU_PRIORITY=5
|
||||||
|
|
||||||
for pattern in "${!container_limits[@]}"; do
|
for pattern in "${!container_limits[@]}"; do
|
||||||
echo "Configuring $container..."
|
echo "Configuring $container..."
|
||||||
|
|
||||||
memory=$DEFAULT_MEMORY
|
memory=$DEFAULT_MEMORY
|
||||||
cpu_allowance=$DEFAULT_CPU_ALLOWANCE
|
cpu_allowance=$DEFAULT_CPU_ALLOWANCE
|
||||||
|
|
||||||
# Configure all containers
|
# Configure all containers
|
||||||
for container in $(lxc list -c n --format csv); do
|
for container in $(lxc list -c n --format csv); do
|
||||||
# Check if container matches any pattern
|
# Check if container matches any pattern
|
||||||
if [[ $container == $pattern ]]; then
|
if [[ $container == $pattern ]]; then
|
||||||
IFS=':' read -r memory cpu_allowance <<< "${container_limits[$pattern]}"
|
IFS=':' read -r memory cpu_allowance <<< "${container_limits[$pattern]}"
|
||||||
|
|
||||||
# Apply configuration
|
# Apply configuration
|
||||||
lxc config set "$container" limits.memory "$memory"
|
lxc config set "$container" limits.memory "$memory"
|
||||||
lxc config set "$container" limits.cpu.allowance "$cpu_allowance"
|
lxc config set "$container" limits.cpu.allowance "$cpu_allowance"
|
||||||
|
@ -50,4 +50,4 @@ for pattern in "${!container_limits[@]}"; do
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
|
@ -93,7 +93,7 @@ async fn start_llama_server() -> Result<(), Box<dyn std::error::Error + Send + S
|
||||||
// Get environment variables for llama.cpp configuration
|
// Get environment variables for llama.cpp configuration
|
||||||
let llama_path = env::var("LLM_CPP_PATH").unwrap_or_else(|_| "llama-server".to_string());
|
let llama_path = env::var("LLM_CPP_PATH").unwrap_or_else(|_| "llama-server".to_string());
|
||||||
let model_path = env::var("LLM_MODEL_PATH")
|
let model_path = env::var("LLM_MODEL_PATH")
|
||||||
.unwrap_or_else(|_| "./models/tinyllama-1.1b-q4_01.gguf".to_string());
|
.unwrap_or_else(|_| "./tinyllama-1.1b-chat-v1.0.Q4_0.gguf".to_string());
|
||||||
let cpu_limit = env::var("CPU_LIMIT").unwrap_or_else(|_| "50".to_string());
|
let cpu_limit = env::var("CPU_LIMIT").unwrap_or_else(|_| "50".to_string());
|
||||||
let port = env::var("LLM_PORT").unwrap_or_else(|_| "8080".to_string());
|
let port = env::var("LLM_PORT").unwrap_or_else(|_| "8080".to_string());
|
||||||
|
|
||||||
|
@ -105,15 +105,15 @@ async fn start_llama_server() -> Result<(), Box<dyn std::error::Error + Send + S
|
||||||
|
|
||||||
// Kill any existing llama processes
|
// Kill any existing llama processes
|
||||||
println!("🧹 Cleaning up existing processes...");
|
println!("🧹 Cleaning up existing processes...");
|
||||||
let _ = Command::new("pkill").arg("-f").arg("llama-server").output();
|
let _ = Command::new("pkill").arg("-f").arg("llama-cli").output();
|
||||||
|
|
||||||
// Wait a bit for cleanup
|
// Wait a bit for cleanup
|
||||||
sleep(Duration::from_secs(2)).await;
|
sleep(Duration::from_secs(2)).await;
|
||||||
|
|
||||||
// Build the command
|
// Build the command
|
||||||
let full_command = format!(
|
let full_command = format!(
|
||||||
"cpulimit -l {} -- {} -m '{}' --n-gpu-layers 18 --temp 0.7 --ctx-size 1024 --batch-size 256 --no-mmap --mlock --port {} --host 127.0.0.1 --tensor-split 1.0 --main-gpu 0",
|
"{}/llama-server -m {} --mlock --port {} --host 127.0.0.1",
|
||||||
cpu_limit, llama_path, model_path, port
|
llama_path, model_path, port
|
||||||
);
|
);
|
||||||
|
|
||||||
println!("📝 Executing command: {}", full_command);
|
println!("📝 Executing command: {}", full_command);
|
||||||
|
@ -238,12 +238,12 @@ fn messages_to_prompt(messages: &[ChatMessage]) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Proxy endpoint
|
// Proxy endpoint
|
||||||
#[post("/v1/chat/completions")]
|
#[post("/v1/chat/completions1")]
|
||||||
pub async fn chat_completions(
|
pub async fn chat_completions_local(
|
||||||
req_body: web::Json<ChatCompletionRequest>,
|
req_body: web::Json<ChatCompletionRequest>,
|
||||||
_req: HttpRequest,
|
_req: HttpRequest,
|
||||||
) -> Result<HttpResponse> {
|
) -> Result<HttpResponse> {
|
||||||
dotenv().ok();
|
dotenv().ok().unwrap();
|
||||||
|
|
||||||
// Ensure llama.cpp server is running
|
// Ensure llama.cpp server is running
|
||||||
if let Err(e) = ensure_llama_server_running().await {
|
if let Err(e) = ensure_llama_server_running().await {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use actix_web::{post, web, HttpRequest, HttpResponse, Result};
|
use actix_web::{post, web, HttpRequest, HttpResponse, Result};
|
||||||
use dotenv::dotenv;
|
use dotenv::dotenv;
|
||||||
|
use regex::Regex;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::env;
|
use std::env;
|
||||||
|
@ -33,12 +34,15 @@ struct Choice {
|
||||||
finish_reason: String,
|
finish_reason: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Proxy endpoint
|
|
||||||
#[post("/v1/chat/completions")]
|
#[post("/v1/chat/completions")]
|
||||||
async fn chat_completions(
|
async fn chat_completions(body: web::Bytes, _req: HttpRequest) -> Result<HttpResponse> {
|
||||||
req_body: web::Json<ChatCompletionRequest>,
|
// Always log raw POST data
|
||||||
_req: HttpRequest,
|
if let Ok(body_str) = std::str::from_utf8(&body) {
|
||||||
) -> Result<HttpResponse> {
|
println!("POST Data: {}", body_str);
|
||||||
|
} else {
|
||||||
|
println!("POST Data (binary): {:?}", body);
|
||||||
|
}
|
||||||
|
|
||||||
dotenv().ok();
|
dotenv().ok();
|
||||||
|
|
||||||
// Environment variables
|
// Environment variables
|
||||||
|
@ -67,12 +71,23 @@ async fn chat_completions(
|
||||||
reqwest::header::HeaderValue::from_static("application/json"),
|
reqwest::header::HeaderValue::from_static("application/json"),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let body_str = std::str::from_utf8(&body).unwrap_or("");
|
||||||
|
println!("Original POST Data: {}", body_str);
|
||||||
|
|
||||||
|
// Remove the problematic params
|
||||||
|
let re =
|
||||||
|
Regex::new(r#","?\s*"(max_completion_tokens|parallel_tool_calls)"\s*:\s*[^,}]*"#).unwrap();
|
||||||
|
let cleaned = re.replace_all(body_str, "");
|
||||||
|
let cleaned_body = web::Bytes::from(cleaned.to_string());
|
||||||
|
|
||||||
|
println!("Cleaned POST Data: {}", cleaned);
|
||||||
|
|
||||||
// Send request to Azure
|
// Send request to Azure
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
let response = client
|
let response = client
|
||||||
.post(&url)
|
.post(&url)
|
||||||
.headers(headers)
|
.headers(headers)
|
||||||
.json(&req_body.into_inner())
|
.body(cleaned_body)
|
||||||
.send()
|
.send()
|
||||||
.await
|
.await
|
||||||
.map_err(actix_web::error::ErrorInternalServerError)?;
|
.map_err(actix_web::error::ErrorInternalServerError)?;
|
||||||
|
@ -88,11 +103,7 @@ async fn chat_completions(
|
||||||
println!("Raw Azure response: {}", raw_response);
|
println!("Raw Azure response: {}", raw_response);
|
||||||
|
|
||||||
if status.is_success() {
|
if status.is_success() {
|
||||||
// Parse the raw response as JSON
|
Ok(HttpResponse::Ok().body(raw_response))
|
||||||
let azure_response: serde_json::Value = serde_json::from_str(&raw_response)
|
|
||||||
.map_err(actix_web::error::ErrorInternalServerError)?;
|
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(azure_response))
|
|
||||||
} else {
|
} else {
|
||||||
// Handle error responses properly
|
// Handle error responses properly
|
||||||
let actix_status = actix_web::http::StatusCode::from_u16(status.as_u16())
|
let actix_status = actix_web::http::StatusCode::from_u16(status.as_u16())
|
||||||
|
|
Loading…
Add table
Reference in a new issue