WIP Rework markdown parsing
This commit is contained in:
parent
604410ef61
commit
d39459f2a9
11 changed files with 109 additions and 42 deletions
38
Cargo.lock
generated
38
Cargo.lock
generated
|
@ -1730,6 +1730,15 @@ dependencies = [
|
||||||
"windows-targets 0.48.5",
|
"windows-targets 0.48.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getopts"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.16"
|
version = "0.1.16"
|
||||||
|
@ -2869,7 +2878,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-targets 0.48.5",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2955,6 +2964,7 @@ dependencies = [
|
||||||
"mime_guess",
|
"mime_guess",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"pulldown-cmark",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"regex",
|
"regex",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
@ -4039,6 +4049,26 @@ dependencies = [
|
||||||
"psl-types",
|
"psl-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pulldown-cmark"
|
||||||
|
version = "0.12.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.8.0",
|
||||||
|
"getopts",
|
||||||
|
"memchr",
|
||||||
|
"pulldown-cmark-escape",
|
||||||
|
"serde",
|
||||||
|
"unicase",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pulldown-cmark-escape"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-xml"
|
name = "quick-xml"
|
||||||
version = "0.37.2"
|
version = "0.37.2"
|
||||||
|
@ -6166,6 +6196,12 @@ version = "1.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.6"
|
version = "0.2.6"
|
||||||
|
|
|
@ -83,6 +83,7 @@ tracing-test = "0.2.4"
|
||||||
sysinfo = { version = "0.30.11", optional = true }
|
sysinfo = { version = "0.30.11", optional = true }
|
||||||
derive_more = { version = "0.99.17", features = ["nightly"] }
|
derive_more = { version = "0.99.17", features = ["nightly"] }
|
||||||
sqlx-macros = { version = "0.7.4", optional = true, features = ["chrono", "json", "migrate", "sqlite", "uuid"] }
|
sqlx-macros = { version = "0.7.4", optional = true, features = ["chrono", "json", "migrate", "sqlite", "uuid"] }
|
||||||
|
pulldown-cmark = { version = "0.12.2", features = ["serde"] }
|
||||||
# qdrant-client = "1.11.2"
|
# qdrant-client = "1.11.2"
|
||||||
# swiftide = "0.9.1"
|
# swiftide = "0.9.1"
|
||||||
|
|
||||||
|
|
|
@ -48,11 +48,15 @@ pub async fn run_starter_task(pool: sqlx::SqlitePool) {
|
||||||
use crate::server::backends::BackendService;
|
use crate::server::backends::BackendService;
|
||||||
let _ = tracing::debug_span!("starter_task");
|
let _ = tracing::debug_span!("starter_task");
|
||||||
|
|
||||||
|
tracing::debug!("AAAAAAAAAAAAAAA");
|
||||||
|
return; // TODO ????
|
||||||
tracing::debug!("Starter task started");
|
tracing::debug!("Starter task started");
|
||||||
|
|
||||||
let service_handle = BackendService::new();
|
let service_handle = BackendService::new();
|
||||||
let mut stream = IntervalStream::new(time::interval(Duration::from_millis(1000)));
|
let mut stream = IntervalStream::new(time::interval(Duration::from_millis(1000)));
|
||||||
while let Some(instant) = stream.next().await {
|
while let Some(instant) = stream.next().await {
|
||||||
|
break; // TODO integrate proxy man ?
|
||||||
|
|
||||||
tracing::debug!("fire; instant={:?}", instant);
|
tracing::debug!("fire; instant={:?}", instant);
|
||||||
|
|
||||||
let waiting_to_start: Vec<BackendProcess> = sqlx::query_as(
|
let waiting_to_start: Vec<BackendProcess> = sqlx::query_as(
|
||||||
|
|
|
@ -41,7 +41,8 @@ pub fn App() -> impl IntoView {
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="" view=MainPage>
|
<Route path="" view=MainPage>
|
||||||
<Route path="/chat" view=ChatPage/>
|
<Route path="/chat" view=ChatPage/>
|
||||||
<SettingsRoutes/>
|
// TODO make settings page for proxy-man
|
||||||
|
// <SettingsRoutes/>
|
||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -12,7 +12,7 @@ use crate::{
|
||||||
app::components::{svgs::*, Card},
|
app::components::{svgs::*, Card},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[component]
|
#[island]
|
||||||
fn ChatMessageBubble(
|
fn ChatMessageBubble(
|
||||||
msg: RwSignal<ChatMessage>,
|
msg: RwSignal<ChatMessage>,
|
||||||
history: RwSignal<Vec<RwSignal<ChatMessage>>>,
|
history: RwSignal<Vec<RwSignal<ChatMessage>>>,
|
||||||
|
@ -33,12 +33,37 @@ fn ChatMessageBubble(
|
||||||
|
|
||||||
let textarea_ref = NodeRef::<html::P>::new();
|
let textarea_ref = NodeRef::<html::P>::new();
|
||||||
|
|
||||||
|
use pulldown_cmark;
|
||||||
let editable_p = move || {
|
let editable_p = move || {
|
||||||
|
// TODO Convert back to raw str when editable
|
||||||
let mode = if edit_mode.get() { "true" } else { "false" };
|
let mode = if edit_mode.get() { "true" } else { "false" };
|
||||||
|
let msg_str = move || msg.get().content.clone();
|
||||||
|
let md_str = move || {
|
||||||
|
let owned_str = msg_str();
|
||||||
|
let parser = pulldown_cmark::Parser::new(&owned_str);
|
||||||
|
let mut md_output = String::new();
|
||||||
|
pulldown_cmark::html::push_html(&mut md_output, parser);
|
||||||
|
|
||||||
|
md_output
|
||||||
|
};
|
||||||
|
|
||||||
|
let inner_p = move || {
|
||||||
|
if edit_mode.get() {
|
||||||
|
view! {
|
||||||
|
|
||||||
|
<p inner_html=move || { msg_str() }></p>
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
view! {
|
||||||
|
<p inner_html=move || { md_str() }></p>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<p node_ref=textarea_ref contenteditable=move || { mode }>
|
<p node_ref=textarea_ref contenteditable=move || { mode }>
|
||||||
|
|
||||||
<span inner_html=msg.get().content.clone()></span>
|
{inner_p}
|
||||||
</p>
|
</p>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,16 +11,16 @@ use crate::api::{ChannelMessage, Chat, ChatMessage};
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
struct LlamaChatCompletionRequest {
|
struct LlamaChatCompletionRequest {
|
||||||
stream: bool,
|
stream: bool,
|
||||||
model: String,
|
model: String,
|
||||||
messages: Vec<LlamaChatMessage>,
|
messages: Vec<LlamaChatMessage>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Chat> for LlamaChatCompletionRequest {
|
impl From<Chat> for LlamaChatCompletionRequest {
|
||||||
fn from(value: Chat) -> Self {
|
fn from(value: Chat) -> Self {
|
||||||
Self {
|
Self {
|
||||||
stream: true,
|
stream: true,
|
||||||
model: "default".to_string(),
|
model: "default".to_string(),
|
||||||
messages: value.history.into_iter().map(|e| e.into()).collect(),
|
messages: value.history.into_iter().map(|e| e.into()).collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,14 +28,14 @@ impl From<Chat> for LlamaChatCompletionRequest {
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
struct LlamaChatMessage {
|
struct LlamaChatMessage {
|
||||||
role: String,
|
role: String,
|
||||||
content: String,
|
content: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ChatMessage> for LlamaChatMessage {
|
impl From<ChatMessage> for LlamaChatMessage {
|
||||||
fn from(chat_message: ChatMessage) -> Self {
|
fn from(chat_message: ChatMessage) -> Self {
|
||||||
Self {
|
Self {
|
||||||
role: chat_message.role.into(),
|
role: chat_message.role.into(),
|
||||||
content: chat_message.content,
|
content: chat_message.content,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,9 +68,7 @@ pub struct LlamaService {
|
||||||
|
|
||||||
impl LlamaService {
|
impl LlamaService {
|
||||||
pub fn new(id: Uuid) -> Self {
|
pub fn new(id: Uuid) -> Self {
|
||||||
Self {
|
Self { id }
|
||||||
id,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +78,8 @@ async fn do_chat_request(chat: Chat, sender: mpsc::Sender<ChannelMessage>) -> an
|
||||||
let request_body: LlamaChatCompletionRequest = chat.into();
|
let request_body: LlamaChatCompletionRequest = chat.into();
|
||||||
|
|
||||||
let request_builder = client
|
let request_builder = client
|
||||||
.post("http://localhost:8080/v1/chat/completions")
|
// # .post("http://localhost:8080/v1/chat/completions")
|
||||||
|
.post("http://100.64.0.3:18080/v1/chat/completions")
|
||||||
.header("Content-Type", "application/json")
|
.header("Content-Type", "application/json")
|
||||||
.json(&request_body);
|
.json(&request_body);
|
||||||
|
|
||||||
|
@ -92,7 +91,19 @@ async fn do_chat_request(chat: Chat, sender: mpsc::Sender<ChannelMessage>) -> an
|
||||||
Ok(Event::Message(event)) => match event.event.as_str() {
|
Ok(Event::Message(event)) => match event.event.as_str() {
|
||||||
"message" => {
|
"message" => {
|
||||||
let data = event.data;
|
let data = event.data;
|
||||||
let response: LlamaChatResponse = serde_json::from_str(&data).unwrap();
|
tracing::debug!(?data);
|
||||||
|
if data == "[DONE]" {
|
||||||
|
sender
|
||||||
|
.send(ChannelMessage::Stop)
|
||||||
|
.await
|
||||||
|
.expect("channel fail");
|
||||||
|
|
||||||
|
es.close();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let response: LlamaChatResponse = serde_json::from_str(&data).expect("no json");
|
||||||
|
|
||||||
for choice in response.choices.into_iter() {
|
for choice in response.choices.into_iter() {
|
||||||
if let Some(delta) = choice.delta {
|
if let Some(delta) = choice.delta {
|
||||||
|
|
|
@ -112,7 +112,7 @@ pub async fn do_completion_request() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let request_body = CompletionRequest::default();
|
let request_body = CompletionRequest::default();
|
||||||
|
|
||||||
let request_builder = client
|
let request_builder = client
|
||||||
.post("http://localhost:8080/completion")
|
.post("http://100.64.0.3:18080/completion")
|
||||||
.header("Accept", "text/event-stream")
|
.header("Accept", "text/event-stream")
|
||||||
.header("Content-Type", "application/json")
|
.header("Content-Type", "application/json")
|
||||||
.header("User-Agent", "llama_forge_rs")
|
.header("User-Agent", "llama_forge_rs")
|
||||||
|
|
|
@ -177,10 +177,7 @@ mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{ChannelMessage, ChatMessage, ChatRole},
|
api::{ChannelMessage, ChatMessage, ChatRole},
|
||||||
server::backends::{
|
server::backends::{
|
||||||
llama_chat::LlamaService,
|
llama_chat::LlamaService, BackendService, BackendServiceStatus, ChatService,
|
||||||
BackendService,
|
|
||||||
BackendServiceStatus,
|
|
||||||
ChatService,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
|
|
||||||
pub struct RunnerArgs {
|
pub struct RunnerArgs {
|
||||||
ctx_size: i64,
|
ctx_size: i64,
|
||||||
gpu_layers: i64,
|
gpu_layers: i64,
|
||||||
model_path: String,
|
model_path: String,
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,8 @@ impl From<RunnerArgs> for Vec<String> {
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Runner {
|
pub struct Runner {
|
||||||
pwd: Option<String>,
|
pwd: Option<String>,
|
||||||
cmd: String,
|
cmd: String,
|
||||||
args: Vec<String>,
|
args: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ impl Runner {
|
||||||
// FIXME does not exit properly when it is killed
|
// FIXME does not exit properly when it is killed
|
||||||
pub fn new_llamafile_bin(runner_args: RunnerArgs) -> Self {
|
pub fn new_llamafile_bin(runner_args: RunnerArgs) -> Self {
|
||||||
Self {
|
Self {
|
||||||
pwd: None,
|
pwd: None,
|
||||||
cmd: "bash".to_string(),
|
cmd: "bash".to_string(),
|
||||||
args: vec![
|
args: vec![
|
||||||
format!(
|
format!(
|
||||||
"{}/llamafile",
|
"{}/llamafile",
|
||||||
|
@ -64,8 +64,8 @@ impl Runner {
|
||||||
|
|
||||||
pub fn new_llama_server_bin(runner_args: RunnerArgs) -> Self {
|
pub fn new_llama_server_bin(runner_args: RunnerArgs) -> Self {
|
||||||
Self {
|
Self {
|
||||||
pwd: None,
|
pwd: None,
|
||||||
cmd: "llama-server".to_string(),
|
cmd: "llama-server".to_string(),
|
||||||
args: runner_args.into(),
|
args: runner_args.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,7 @@ impl<S> Layer<S> for LoggingLayer {
|
||||||
type Service = LoggingService<S>;
|
type Service = LoggingService<S>;
|
||||||
|
|
||||||
fn layer(&self, inner: S) -> Self::Service {
|
fn layer(&self, inner: S) -> Self::Service {
|
||||||
LoggingService {
|
LoggingService { inner }
|
||||||
inner,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,8 +48,8 @@ where
|
||||||
|
|
||||||
LoggingServiceFuture {
|
LoggingServiceFuture {
|
||||||
inner: self.inner.call(req),
|
inner: self.inner.call(req),
|
||||||
uuid: Arc::new(request_uuid), // Store UUID in an Arc for shared ownership
|
uuid: Arc::new(request_uuid), // Store UUID in an Arc for shared ownership
|
||||||
span: Arc::new(span),
|
span: Arc::new(span),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,26 +6,20 @@ use axum::{
|
||||||
http::Request,
|
http::Request,
|
||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
routing::get,
|
routing::get,
|
||||||
Extension,
|
Extension, Router,
|
||||||
Router,
|
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos_axum::{generate_route_list, handle_server_fns_with_context, LeptosRoutes};
|
use leptos_axum::{generate_route_list, handle_server_fns_with_context, LeptosRoutes};
|
||||||
use leptos_router::RouteListing;
|
use leptos_router::RouteListing;
|
||||||
use sqlx::{
|
use sqlx::{
|
||||||
sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions, SqliteSynchronous},
|
sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions, SqliteSynchronous},
|
||||||
ConnectOptions,
|
ConnectOptions, SqlitePool,
|
||||||
SqlitePool,
|
|
||||||
};
|
};
|
||||||
use tower::Layer;
|
use tower::Layer;
|
||||||
use tower_http::{
|
use tower_http::{
|
||||||
compression::CompressionLayer,
|
compression::CompressionLayer,
|
||||||
trace::{
|
trace::{
|
||||||
DefaultMakeSpan,
|
DefaultMakeSpan, DefaultOnEos, DefaultOnFailure, DefaultOnRequest, DefaultOnResponse,
|
||||||
DefaultOnEos,
|
|
||||||
DefaultOnFailure,
|
|
||||||
DefaultOnRequest,
|
|
||||||
DefaultOnResponse,
|
|
||||||
TraceLayer,
|
TraceLayer,
|
||||||
},
|
},
|
||||||
CompressionLevel,
|
CompressionLevel,
|
||||||
|
@ -122,7 +116,7 @@ pub async fn app(leptos_options: LeptosOptions) -> Router {
|
||||||
|
|
||||||
let pool = new_pool().await.expect("pool err");
|
let pool = new_pool().await.expect("pool err");
|
||||||
|
|
||||||
// TODO move this out of server(pool has to be moved out too)
|
// // TODO move this out of server(pool has to be moved out too)
|
||||||
let task = run_starter_task(pool.clone());
|
let task = run_starter_task(pool.clone());
|
||||||
tokio::task::spawn(task);
|
tokio::task::spawn(task);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue