mirror of
https://github.com/perstarkse/minne.git
synced 2026-04-29 12:17:08 +02:00
wip: chat interface
This commit is contained in:
124
src/server/routes/html/chat/mod.rs
Normal file
124
src/server/routes/html/chat/mod.rs
Normal file
@@ -0,0 +1,124 @@
|
||||
use axum::{
|
||||
extract::State,
|
||||
response::{IntoResponse, Redirect},
|
||||
Form,
|
||||
};
|
||||
use axum_session_auth::AuthSession;
|
||||
use axum_session_surreal::SessionSurrealPool;
|
||||
use surrealdb::{engine::any::Any, Surreal};
|
||||
use tracing::info;
|
||||
|
||||
use crate::{
|
||||
error::HtmlError,
|
||||
page_data,
|
||||
server::{routes::html::render_template, AppState},
|
||||
storage::types::user::User,
|
||||
};
|
||||
|
||||
// Update your ChatStartParams struct to properly deserialize the references
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct ChatStartParams {
|
||||
user_query: String,
|
||||
llm_response: String,
|
||||
#[serde(deserialize_with = "deserialize_references")]
|
||||
references: Vec<String>,
|
||||
}
|
||||
|
||||
// Custom deserializer function
|
||||
fn deserialize_references<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
serde_json::from_str(&s).map_err(serde::de::Error::custom)
|
||||
}
|
||||
|
||||
page_data!(ChatData, "chat/base.html", {
|
||||
user: User,
|
||||
history: Vec<Message>,
|
||||
});
|
||||
|
||||
#[derive(Deserialize, Debug, Serialize)]
|
||||
pub enum MessageRole {
|
||||
User,
|
||||
AI,
|
||||
System,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Serialize)]
|
||||
pub struct Message {
|
||||
conversation_id: String,
|
||||
role: MessageRole,
|
||||
content: String,
|
||||
references: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
pub struct Conversation {
|
||||
user_id: String,
|
||||
title: String,
|
||||
}
|
||||
|
||||
pub async fn show_initialized_chat(
|
||||
State(state): State<AppState>,
|
||||
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
|
||||
Form(form): Form<ChatStartParams>,
|
||||
) -> Result<impl IntoResponse, HtmlError> {
|
||||
info!("Displaying chat start");
|
||||
|
||||
let user = match auth.current_user {
|
||||
Some(user) => user,
|
||||
None => return Ok(Redirect::to("/").into_response()),
|
||||
};
|
||||
|
||||
info!("{:?}", form);
|
||||
|
||||
let user_message = Message {
|
||||
conversation_id: "test".to_string(),
|
||||
role: MessageRole::User,
|
||||
content: form.user_query,
|
||||
references: None,
|
||||
};
|
||||
|
||||
let ai_message = Message {
|
||||
conversation_id: "test".to_string(),
|
||||
role: MessageRole::AI,
|
||||
content: form.llm_response,
|
||||
references: Some(form.references),
|
||||
};
|
||||
|
||||
let messages = vec![user_message, ai_message];
|
||||
|
||||
let output = render_template(
|
||||
ChatData::template_name(),
|
||||
ChatData {
|
||||
history: messages,
|
||||
user,
|
||||
},
|
||||
state.templates.clone(),
|
||||
)?;
|
||||
|
||||
Ok(output.into_response())
|
||||
}
|
||||
|
||||
pub async fn show_chat_base(
|
||||
State(state): State<AppState>,
|
||||
auth: AuthSession<User, String, SessionSurrealPool<Any>, Surreal<Any>>,
|
||||
) -> Result<impl IntoResponse, HtmlError> {
|
||||
info!("Displaying empty chat start");
|
||||
|
||||
let user = match auth.current_user {
|
||||
Some(user) => user,
|
||||
None => return Ok(Redirect::to("/").into_response()),
|
||||
};
|
||||
|
||||
let output = render_template(
|
||||
ChatData::template_name(),
|
||||
ChatData {
|
||||
history: vec![],
|
||||
user,
|
||||
},
|
||||
state.templates.clone(),
|
||||
)?;
|
||||
|
||||
Ok(output.into_response())
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use crate::error::{HtmlError, IntoHtmlError};
|
||||
|
||||
pub mod account;
|
||||
pub mod admin_panel;
|
||||
pub mod chat;
|
||||
pub mod content;
|
||||
pub mod documentation;
|
||||
pub mod gdpr;
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
use axum::{
|
||||
extract::{Query, State},
|
||||
response::{Html, IntoResponse, Redirect},
|
||||
response::{IntoResponse, Redirect},
|
||||
};
|
||||
use axum_session_auth::AuthSession;
|
||||
use axum_session_surreal::SessionSurrealPool;
|
||||
use serde::Deserialize;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use surrealdb::{engine::any::Any, Surreal};
|
||||
use tracing::info;
|
||||
|
||||
use crate::{
|
||||
error::HtmlError, retrieval::query_helper::get_answer_with_references, server::AppState,
|
||||
error::HtmlError,
|
||||
retrieval::query_helper::get_answer_with_references,
|
||||
server::{routes::html::render_template, AppState},
|
||||
storage::types::user::User,
|
||||
};
|
||||
#[derive(Deserialize)]
|
||||
@@ -17,6 +19,13 @@ pub struct SearchParams {
|
||||
query: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct AnswerData {
|
||||
user_query: String,
|
||||
answer_content: String,
|
||||
answer_references: Vec<String>,
|
||||
}
|
||||
|
||||
pub async fn search_result_handler(
|
||||
State(state): State<AppState>,
|
||||
Query(query): Query<SearchParams>,
|
||||
@@ -26,17 +35,37 @@ pub async fn search_result_handler(
|
||||
|
||||
let user = match auth.current_user {
|
||||
Some(user) => user,
|
||||
None => return Ok(Redirect::to("/").into_response()),
|
||||
None => return Ok(Redirect::to("/signin").into_response()),
|
||||
};
|
||||
|
||||
let answer = get_answer_with_references(
|
||||
&state.surreal_db_client,
|
||||
&state.openai_client,
|
||||
&query.query,
|
||||
&user.id,
|
||||
)
|
||||
.await
|
||||
.map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
||||
// let answer = get_answer_with_references(
|
||||
// &state.surreal_db_client,
|
||||
// &state.openai_client,
|
||||
// &query.query,
|
||||
// &user.id,
|
||||
// )
|
||||
// .await
|
||||
// .map_err(|e| HtmlError::new(e, state.templates.clone()))?;
|
||||
|
||||
Ok(Html(answer.content).into_response())
|
||||
let answer = "The Minne project is focused on simplifying knowledge management through features such as easy capture, smart analysis, and visualization of connections between ideas. It includes various functionalities like the Smart Analysis Feature, which provides content analysis and organization, and the Easy Capture Feature, which allows users to effortlessly capture and retrieve knowledge in various formats. Additionally, it offers tools like Knowledge Graph Visualization to enhance understanding and organization of knowledge. The project also emphasizes a user-friendly onboarding experience and mobile-friendly options for accessing its services.".to_string();
|
||||
|
||||
let references = vec![
|
||||
"i81cd5be8-557c-4b2b-ba3a-4b8d28e74b9b".to_string(),
|
||||
"5f72a724-d7a3-467d-8783-7cca6053ddc7".to_string(),
|
||||
"ad106a1f-ccda-415e-9e87-c3a34e202624".to_string(),
|
||||
"8797b57d-094d-4ee9-a3a7-c3195b246254".to_string(),
|
||||
"69763f43-82e6-4cb5-ba3e-f6da13777dab".to_string(),
|
||||
];
|
||||
|
||||
let output = render_template(
|
||||
"index/signed_in/search_response.html",
|
||||
AnswerData {
|
||||
user_query: query.query,
|
||||
answer_content: answer,
|
||||
answer_references: references,
|
||||
},
|
||||
state.templates,
|
||||
)?;
|
||||
|
||||
Ok(output.into_response())
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ use axum_session_surreal::SessionSurrealPool;
|
||||
use html::{
|
||||
account::{delete_account, set_api_key, show_account_page, update_timezone},
|
||||
admin_panel::{show_admin_panel, toggle_registration_status},
|
||||
chat::{show_chat_base, show_initialized_chat},
|
||||
content::{patch_text_content, show_content_page, show_text_content_edit_form},
|
||||
documentation::{
|
||||
show_documentation_index, show_get_started, show_mobile_friendly, show_privacy_policy,
|
||||
@@ -63,6 +64,7 @@ pub fn html_routes(app_state: &AppState) -> Router<AppState> {
|
||||
.route("/gdpr/accept", post(accept_gdpr))
|
||||
.route("/gdpr/deny", post(deny_gdpr))
|
||||
.route("/search", get(search_result_handler))
|
||||
.route("/chat", get(show_chat_base).post(show_initialized_chat))
|
||||
.route("/signout", get(sign_out_user))
|
||||
.route("/signin", get(show_signin_form).post(authenticate_user))
|
||||
.route(
|
||||
|
||||
Reference in New Issue
Block a user