From 60b89ebeaaec707187110c72acc769c4bfe596c9 Mon Sep 17 00:00:00 2001 From: retoor <retoor@molodetz.nl> Date: Mon, 17 Mar 2025 00:50:39 +0100 Subject: [PATCH] Update. --- .gitignore | 4 ++ Cargo.toml | 17 ++++++++ Makefile | 13 ++++++ src/lib.rs | 81 +++++++++++++++++++++++++++++++++++ src/main.rs | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 236 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 Makefile create mode 100644 src/lib.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0607932 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/target +.r_history +Cargo.lock +*.zip diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..11f98c1 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "rullama" +version = "0.1.0" +edition = "2018" + +[lib] +crate-type = ["cdylib", "rlib"] + + + +[dependencies] +clap = "2.33.3" +structopt = "0.3.24" +reqwest = { version = "0.11", features = ["blocking", "json"] } +serde_json = "1.0" +wasm-bindgen = "0.2" + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fd7ad60 --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ + +all: build run + +build: + cargo build --release + +run: + ./target/release/rullama + +backup: + @timestamp=$$(date +%Y%m%d_%H%M%S); \ + zip -r rollama_$$timestamp.zip Makefile Cargo.toml src target/release/rullama + diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..9a1ae87 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,81 @@ +use wasm_bindgen::prelude::wasm_bindgen; + +use reqwest::blocking::Client; +use serde_json::json; +use std::io; + +#[wasm_bindgen] +pub fn your_cool_function(input: &str) -> String { + format!("Processed: {}", input) +} + +fn main() { + let client = Client::builder() + .timeout(std::time::Duration::from_secs(600)) + .build() + .unwrap(); + + println!("AI Chat! Type your message below (or type 'exit' to quit):"); + + let mut messages = Vec::new(); + + loop { + let mut prompt = String::new(); + io::stdin().read_line(&mut prompt).expect("Failed to read line"); + let prompt = prompt.trim(); + if prompt.eq_ignore_ascii_case("exit") { + println!("Goodbye!"); + break; + } + + messages.push(json!({ + "role": "user", + "content": prompt + })); + + let response = client.post("https://ollama.molodetz.nl/api/chat") + .header("Content-Type", "application/json") + .body(json!({ + "model": "qwen2.5:1.5b", + "messages": messages + }).to_string()) + .send(); + + match response { + Ok(resp) => { + match resp.bytes() { + Ok(data) => { + let raw_text = String::from_utf8_lossy(&data); + let mut lines = raw_text.lines(); + while let Some(line) = lines.next() { + match serde_json::from_str::<serde_json::Value>(line) { + Ok(json_response) => { + if let Some(message) = json_response.get("message") { + if let Some(content) = message.get("content") { + if let Some(s) = content.as_str() { + print!("{}", s); + } + } + } else { + println!("No message found."); + } + } + Err(e) => { + println!("Failed to parse JSON: {:?}", e); + } + } + } + } + Err(e) => { + eprintln!("Error reading response: {:?}", e); + } + } + println!(""); + } + + Err(e) => { + eprintln!("Error: {:?}", e); + } + } + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..d9e880c --- /dev/null +++ b/src/main.rs @@ -0,0 +1,121 @@ +use wasm_bindgen::prelude::wasm_bindgen; + +use reqwest::blocking::Client; +use serde_json::json; +use std::env; +use std::fs; +use std::io; + +// Author: retoor@molodetz.nl + + +// Simple file description / purpose + + +// MIT License +// +// 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: +// +// ... (full license text) + + +#[wasm_bindgen] +pub fn your_cool_function(input: &str) -> String { + // Your logic here + format!("Processed: {}", input) +} + +fn main() { + let args: Vec<String> = env::args().collect(); + let file_content = if args.len() > 1 { + let file_path = &args[1]; + fs::read_to_string(file_path).unwrap_or_else(|_| { + eprintln!("Failed to read file: {}", file_path); + String::new() + }) + } else { + String::new() + }; + + let client = Client::builder() + .timeout(std::time::Duration::from_secs(600)) + .build() + .unwrap(); + + println!("AI Chat! Type your message below (or type 'exit' to quit):"); + + loop { + let mut prompt = String::new(); + io::stdin().read_line(&mut prompt).expect("Failed to read line"); + let prompt = prompt.trim(); + if prompt.eq_ignore_ascii_case("exit") { + println!("Goodbye!"); + break; + } + + let message = if !file_content.is_empty() { + format!("{}\n{}", file_content, prompt) + } else { + prompt.to_string() + }; + + let response = client.post("https://ollama.molodetz.nl/api/chat") + .header("Content-Type", "application/json") + .body(json!({ + "model": "qwen2.5:1.5b", + "messages": [ + { + "role": "user", + "content": message + } + ] + }).to_string()) + .send(); + + match response { + Ok(resp) => { + match resp.bytes() { + Ok(data) => { + let raw_text = String::from_utf8_lossy(&data); + //println!("Raw response: {}", raw_text); + let mut lines = raw_text.lines(); + while let Some(line) = lines.next() { + match serde_json::from_str::<serde_json::Value>(line) { + Ok(json_response) => { + if let Some(message) = json_response.get("message") { + if let Some(content) = message.get("content") { + if let Some(s) = content.as_str() { + + print!("{}", s); + } + + } + } else { + println!("No message found."); + } + } + Err(e) => { + println!("Failed to parse JSON: {:?}", e); + } + } + } + } + Err(e) => { + eprintln!("Error reading response: {:?}", e); + } + } + + println!(""); + } + + Err(e) => { + eprintln!("Error: {:?}", e); + } + } + } +}