implement initial llm features

This commit is contained in:
yggverse 2026-01-08 14:05:16 +02:00
parent 5608e2e081
commit de3fda435a
10 changed files with 269 additions and 14 deletions

View file

@ -0,0 +1,37 @@
use clap::Parser;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
pub struct Argument {
// LLM
#[arg(long, default_value_t = String::from("http"))]
pub llm_scheme: String,
#[arg(long, default_value_t = String::from("localhost"))]
pub llm_host: String,
#[arg(long, default_value_t = 8080)]
pub llm_port: u16,
/// Model name (e.g. `INSAIT-Institute/MamayLM-Gemma-2-9B-IT-v0.1-GGUF` or `ggml-org/gemma-3-1b-it-GGUF`)
#[arg(long)]
pub llm_model: String,
/// Initial message for the `content` subject (e.g. `translate to...`)
#[arg(long)]
pub llm_message: String,
// Database
#[arg(long, default_value_t = String::from("localhost"))]
pub mysql_host: String,
#[arg(long, default_value_t = 3306)]
pub mysql_port: u16,
#[arg(long)]
pub mysql_username: String,
#[arg(long)]
pub mysql_password: String,
#[arg(long)]
pub mysql_database: String,
/// Loop update in seconds
/// * None to exit on complete
#[arg(long, short)]
pub update: Option<u64>,
}

103
crates/llm/src/main.rs Normal file
View file

@ -0,0 +1,103 @@
mod argument;
use anyhow::Result;
#[tokio::main]
async fn main() -> Result<()> {
use argument::Argument;
use chrono::Local;
use clap::Parser;
use lancor::{ChatCompletionRequest, LlamaCppClient, Message};
use log::{debug, info};
use mysql::{Mysql, Sort};
use std::env::var;
if var("RUST_LOG").is_ok() {
use tracing_subscriber::{EnvFilter, fmt::*};
struct T;
impl time::FormatTime for T {
fn format_time(&self, w: &mut format::Writer<'_>) -> std::fmt::Result {
write!(w, "{}", Local::now())
}
}
fmt()
.with_timer(T)
.with_env_filter(EnvFilter::from_default_env())
.init()
}
let arg = Argument::parse();
let db = Mysql::connect(
&arg.mysql_host,
arg.mysql_port,
&arg.mysql_username,
&arg.mysql_password,
&arg.mysql_database,
)?;
let llm = LlamaCppClient::new(format!(
"{}://{}:{}",
arg.llm_scheme, arg.llm_host, arg.llm_port
))?;
let provider_id = match db.provider_by_name(&arg.llm_model)? {
Some(p) => {
debug!(
"Use existing DB provider #{} matches model name `{}`",
p.provider_id, &arg.llm_model
);
p.provider_id
}
None => {
let provider_id = db.insert_provider(&arg.llm_model)?;
info!(
"Provider `{}` not found in database, created new one with ID `{provider_id}`",
&arg.llm_model
);
provider_id
}
};
info!("Daemon started");
loop {
debug!("New queue begin...");
for source in db.contents_queue_for_provider_id(provider_id, Sort::Asc, None)? {
debug!(
"Begin generating `content_id` #{} using `provider_id` #{provider_id}.",
source.content_id
);
let title =
llm.chat_completion(ChatCompletionRequest::new(&arg.llm_model).message(
Message::user(format!("{}\n{}", arg.llm_message, source.title)),
))
.await?;
println!("{}", &title.choices[0].message.content);
let description =
llm.chat_completion(ChatCompletionRequest::new(&arg.llm_model).message(
Message::user(format!("{}\n{}", arg.llm_message, source.description)),
))
.await?;
let content_id = db.insert_content(
source.channel_item_id,
Some(provider_id),
&title.choices[0].message.content,
&description.choices[0].message.content,
)?;
debug!(
"Created `content_id` #{content_id} using `content_id` #{} source by `provider_id` #{provider_id}.",
source.content_id
)
}
debug!("Queue completed");
if let Some(update) = arg.update {
debug!("Wait {update} seconds to continue...");
std::thread::sleep(std::time::Duration::from_secs(update))
} else {
return Ok(());
}
}
}