refactor: postgres files
This commit is contained in:
@@ -0,0 +1,66 @@
|
|||||||
|
use crate::databases::postgres::errors::DbError;
|
||||||
|
use crate::providers::ollama::errors::OllamaError;
|
||||||
|
|
||||||
|
use axum::http::StatusCode;
|
||||||
|
use axum::response::{IntoResponse, Response};
|
||||||
|
|
||||||
|
pub enum ApiError {
|
||||||
|
Db(DbError),
|
||||||
|
Ollama(OllamaError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DbError> for ApiError {
|
||||||
|
fn from(e: DbError) -> Self {
|
||||||
|
ApiError::Db(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<OllamaError> for ApiError {
|
||||||
|
fn from(e: OllamaError) -> Self {
|
||||||
|
ApiError::Ollama(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoResponse for ApiError {
|
||||||
|
fn into_response(self) -> Response {
|
||||||
|
let (status, msg) = match self {
|
||||||
|
ApiError::Db(db_err) => match db_err {
|
||||||
|
DbError::Connection(_) => (
|
||||||
|
StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
"database connection error".to_string(),
|
||||||
|
),
|
||||||
|
DbError::Timeout => (StatusCode::REQUEST_TIMEOUT, "database timeout".to_string()),
|
||||||
|
DbError::NotFound => (StatusCode::NOT_FOUND, "not found".to_string()),
|
||||||
|
},
|
||||||
|
|
||||||
|
ApiError::Ollama(ollama_err) => match ollama_err {
|
||||||
|
OllamaError::MissingPrompt => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
"prompt is required and cannot be empty".to_string(),
|
||||||
|
),
|
||||||
|
OllamaError::MissingModel => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
"model is required and cannot be empty".to_string(),
|
||||||
|
),
|
||||||
|
OllamaError::ModelNotFound(m) => (
|
||||||
|
StatusCode::UNPROCESSABLE_ENTITY,
|
||||||
|
format!("model '{m}' is not available — run `ollama pull {m}` first"),
|
||||||
|
),
|
||||||
|
OllamaError::MissingKeepAlive => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
"keep alive is required and cannot be empty".to_string(),
|
||||||
|
),
|
||||||
|
OllamaError::InvalidKeepAlive(v) => {
|
||||||
|
(StatusCode::BAD_REQUEST, format!("invalid keep_alive '{v}'"))
|
||||||
|
}
|
||||||
|
OllamaError::MissingMessages => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
"messages array with at least one user message is required".to_string(),
|
||||||
|
),
|
||||||
|
OllamaError::Http(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
(status, msg).into_response()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
pub mod errors;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
pub mod queries;
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
use super::errors::DbError;
|
use crate::databases::postgres::errors::DbError;
|
||||||
|
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod queries;
|
||||||
|
pub mod types;
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
use super::errors::DbError;
|
use crate::databases::postgres::chat::types;
|
||||||
use crate::dto::postgres;
|
use crate::databases::postgres::errors::DbError;
|
||||||
|
|
||||||
use sqlx::{Acquire, PgPool};
|
use sqlx::{Acquire, PgPool};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -39,17 +40,11 @@ where
|
|||||||
Ok(rec.id)
|
Ok(rec.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum ConversationState {
|
|
||||||
Existing(Uuid),
|
|
||||||
Created(Uuid),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn get_or_create_conversation(
|
pub async fn get_or_create_conversation(
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
conversation_id: Option<Uuid>,
|
conversation_id: Option<Uuid>,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
) -> Result<ConversationState, DbError> {
|
) -> Result<types::ConversationState, DbError> {
|
||||||
tracing::debug!("Testing conversation");
|
tracing::debug!("Testing conversation");
|
||||||
|
|
||||||
let mut tx = pool.begin().await?;
|
let mut tx = pool.begin().await?;
|
||||||
@@ -65,9 +60,11 @@ pub async fn get_or_create_conversation(
|
|||||||
match conversation_id {
|
match conversation_id {
|
||||||
Some(id) => {
|
Some(id) => {
|
||||||
validate_conversation(&mut *conn, id).await?;
|
validate_conversation(&mut *conn, id).await?;
|
||||||
ConversationState::Existing(id)
|
types::ConversationState::Existing(id)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
types::ConversationState::Created(create_conversation(&mut *conn, user_id).await?)
|
||||||
}
|
}
|
||||||
None => ConversationState::Created(create_conversation(&mut *conn, user_id).await?),
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -101,21 +98,12 @@ pub async fn set_conversation_title(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, sqlx::Type)]
|
|
||||||
#[sqlx(type_name = "text")]
|
|
||||||
#[sqlx(rename_all = "lowercase")]
|
|
||||||
pub enum MessageRole {
|
|
||||||
User,
|
|
||||||
Assistant,
|
|
||||||
System,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn insert_message(
|
pub async fn insert_message(
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
conversation_id: Uuid,
|
conversation_id: Uuid,
|
||||||
parent_id: Option<Uuid>,
|
parent_id: Option<Uuid>,
|
||||||
role: MessageRole,
|
role: types::MessageRole,
|
||||||
content: &str,
|
content: &str,
|
||||||
tokens: Option<u32>,
|
tokens: Option<u32>,
|
||||||
) -> Result<Uuid, DbError> {
|
) -> Result<Uuid, DbError> {
|
||||||
@@ -135,7 +123,7 @@ pub async fn insert_message(
|
|||||||
"#,
|
"#,
|
||||||
conversation_id,
|
conversation_id,
|
||||||
parent_id,
|
parent_id,
|
||||||
role as MessageRole,
|
role as types::MessageRole,
|
||||||
content,
|
content,
|
||||||
tokens.unwrap_or(0) as i32
|
tokens.unwrap_or(0) as i32
|
||||||
)
|
)
|
||||||
@@ -178,8 +166,8 @@ pub async fn get_conversations_entries(
|
|||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
limit: i64,
|
limit: i64,
|
||||||
before: Option<chrono::DateTime<chrono::Utc>>, // cursor
|
before: Option<chrono::DateTime<chrono::Utc>>,
|
||||||
) -> Result<Vec<postgres::ConversationSummary>, DbError> {
|
) -> Result<Vec<types::ConversationSummary>, DbError> {
|
||||||
let mut tx = pool.begin().await?;
|
let mut tx = pool.begin().await?;
|
||||||
|
|
||||||
sqlx::query("SELECT set_config('app.current_user_id', $1::text, true)")
|
sqlx::query("SELECT set_config('app.current_user_id', $1::text, true)")
|
||||||
@@ -188,7 +176,7 @@ pub async fn get_conversations_entries(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let rows = sqlx::query_as!(
|
let rows = sqlx::query_as!(
|
||||||
postgres::ConversationSummary,
|
types::ConversationSummary,
|
||||||
r#"
|
r#"
|
||||||
SELECT id, title, created_at, updated_at
|
SELECT id, title, created_at, updated_at
|
||||||
FROM chat.conversation
|
FROM chat.conversation
|
||||||
@@ -214,7 +202,7 @@ pub async fn get_conversation_messages(
|
|||||||
conversation_id: Uuid,
|
conversation_id: Uuid,
|
||||||
limit: i64,
|
limit: i64,
|
||||||
before: Option<chrono::DateTime<chrono::Utc>>,
|
before: Option<chrono::DateTime<chrono::Utc>>,
|
||||||
) -> Result<Vec<postgres::MessageSummary>, DbError> {
|
) -> Result<Vec<types::MessageSummary>, DbError> {
|
||||||
let mut conn = pool.acquire().await?;
|
let mut conn = pool.acquire().await?;
|
||||||
|
|
||||||
sqlx::query(r#"SELECT set_config('app.current_user_id', $1::text, true)"#)
|
sqlx::query(r#"SELECT set_config('app.current_user_id', $1::text, true)"#)
|
||||||
@@ -223,7 +211,7 @@ pub async fn get_conversation_messages(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let rows = sqlx::query_as!(
|
let rows = sqlx::query_as!(
|
||||||
postgres::MessageSummary,
|
types::MessageSummary,
|
||||||
r#"
|
r#"
|
||||||
SELECT id, parent_id, role, content, created_at, tokens
|
SELECT id, parent_id, role, content, created_at, tokens
|
||||||
FROM chat.message
|
FROM chat.message
|
||||||
@@ -1,6 +1,21 @@
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, sqlx::Type)]
|
||||||
|
#[sqlx(type_name = "text")]
|
||||||
|
#[sqlx(rename_all = "lowercase")]
|
||||||
|
pub enum MessageRole {
|
||||||
|
User,
|
||||||
|
Assistant,
|
||||||
|
System,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ConversationState {
|
||||||
|
Existing(Uuid),
|
||||||
|
Created(Uuid),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, sqlx::FromRow, Serialize)]
|
#[derive(Debug, sqlx::FromRow, Serialize)]
|
||||||
pub struct ConversationSummary {
|
pub struct ConversationSummary {
|
||||||
pub id: Uuid,
|
pub id: Uuid,
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
use axum::http::StatusCode;
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
@@ -12,14 +11,3 @@ pub enum DbError {
|
|||||||
#[error("not found")]
|
#[error("not found")]
|
||||||
NotFound,
|
NotFound,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_http_response(e: DbError) -> (StatusCode, String) {
|
|
||||||
match e {
|
|
||||||
DbError::Connection(_) => (
|
|
||||||
StatusCode::INTERNAL_SERVER_ERROR,
|
|
||||||
"database connection error".to_string(),
|
|
||||||
),
|
|
||||||
DbError::Timeout => (StatusCode::REQUEST_TIMEOUT, "database timeout".to_string()),
|
|
||||||
DbError::NotFound => (StatusCode::NOT_FOUND, "not found".to_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
pub mod api_key;
|
|
||||||
pub mod chat;
|
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod pool;
|
pub mod pool;
|
||||||
|
|
||||||
|
pub mod api_key;
|
||||||
|
pub mod chat;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
pub mod queries;
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
use super::errors::DbError;
|
use crate::databases::postgres::errors::DbError;
|
||||||
|
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
+3
-3
@@ -234,8 +234,8 @@ pub struct ConversationQuery {
|
|||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub struct ConversationListResponse {
|
pub struct ConversationListResponse {
|
||||||
pub conversations: Vec<super::postgres::ConversationSummary>,
|
pub conversations: Vec<crate::databases::postgres::chat::types::ConversationSummary>,
|
||||||
pub has_more: bool, // client knows if there are more pages
|
pub has_more: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
@@ -246,6 +246,6 @@ pub struct MessageQuery {
|
|||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub struct MessageListResponse {
|
pub struct MessageListResponse {
|
||||||
pub messages: Vec<super::postgres::MessageSummary>,
|
pub messages: Vec<crate::databases::postgres::chat::types::MessageSummary>,
|
||||||
pub has_more: bool,
|
pub has_more: bool,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
pub mod api;
|
pub mod api;
|
||||||
pub mod ollama;
|
pub mod ollama;
|
||||||
pub mod postgres;
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
pub mod api;
|
||||||
pub mod databases;
|
pub mod databases;
|
||||||
pub mod dto;
|
pub mod dto;
|
||||||
pub mod middlewares;
|
pub mod middlewares;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
mod api;
|
||||||
mod databases;
|
mod databases;
|
||||||
mod docs;
|
mod docs;
|
||||||
mod dto;
|
mod dto;
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ use axum::{
|
|||||||
response::{IntoResponse, Response},
|
response::{IntoResponse, Response},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::databases::postgres::{api_key::update_last_access, user::ensure_user_exists};
|
use crate::databases::postgres::{
|
||||||
|
api_key::queries::update_last_access, user::queries::ensure_user_exists,
|
||||||
|
};
|
||||||
use crate::middlewares::auth::apikey::{ApiKeyClaims, ApiKeyClaimsRoles};
|
use crate::middlewares::auth::apikey::{ApiKeyClaims, ApiKeyClaimsRoles};
|
||||||
use crate::middlewares::auth::keycloak::{KeycloakClaims, get_jwks, refresh_jwks, validate_token};
|
use crate::middlewares::auth::keycloak::{KeycloakClaims, get_jwks, refresh_jwks, validate_token};
|
||||||
use crate::state::app_state::AppState;
|
use crate::state::app_state::AppState;
|
||||||
|
|||||||
+27
-49
@@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
databases::postgres::chat::ConversationState, dto::api::BaseLLMRequest,
|
dto::api::BaseLLMRequest, middlewares::auth::middleware::Auth,
|
||||||
middlewares::auth::middleware::Auth, providers::ollama::client::OllamaProvider,
|
providers::ollama::client::OllamaProvider,
|
||||||
};
|
};
|
||||||
use axum::{
|
use axum::{
|
||||||
Json,
|
Json,
|
||||||
@@ -14,13 +14,14 @@ use sqlx::PgPool;
|
|||||||
use tokio_stream::StreamExt;
|
use tokio_stream::StreamExt;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::databases::postgres::chat::{
|
use crate::api::errors::ApiError;
|
||||||
|
use crate::databases::postgres::chat::queries::{
|
||||||
get_conversation_messages, get_conversations_entries, get_or_create_conversation,
|
get_conversation_messages, get_conversations_entries, get_or_create_conversation,
|
||||||
set_conversation_title, update_message_tokens,
|
insert_message, set_conversation_title, update_message_tokens,
|
||||||
};
|
};
|
||||||
use crate::databases::postgres::{chat, errors};
|
use crate::databases::postgres::chat::types::{ConversationState, MessageRole};
|
||||||
|
use crate::databases::postgres::errors;
|
||||||
use crate::dto::api;
|
use crate::dto::api;
|
||||||
use crate::dto::api::CompletionRequest;
|
|
||||||
use crate::providers::ollama::errors::into_http_response;
|
use crate::providers::ollama::errors::into_http_response;
|
||||||
use crate::state::app_state::AppState;
|
use crate::state::app_state::AppState;
|
||||||
|
|
||||||
@@ -89,11 +90,9 @@ async fn ensure_conversation(
|
|||||||
auth: &Auth,
|
auth: &Auth,
|
||||||
conversation_id: Option<Uuid>,
|
conversation_id: Option<Uuid>,
|
||||||
first_message: &str,
|
first_message: &str,
|
||||||
) -> Result<Uuid, (axum::http::StatusCode, String)> {
|
) -> Result<Uuid, ApiError> {
|
||||||
let conversation_state =
|
let conversation_state =
|
||||||
get_or_create_conversation(&state.postgres, conversation_id, auth.user_id())
|
get_or_create_conversation(&state.postgres, conversation_id, auth.user_id()).await?;
|
||||||
.await
|
|
||||||
.map_err(crate::databases::postgres::errors::into_http_response)?;
|
|
||||||
|
|
||||||
let id = match conversation_state {
|
let id = match conversation_state {
|
||||||
ConversationState::Existing(uuid) => uuid,
|
ConversationState::Existing(uuid) => uuid,
|
||||||
@@ -127,14 +126,10 @@ async fn handle_stream(
|
|||||||
auth: Auth,
|
auth: Auth,
|
||||||
body: api::ChatRequest,
|
body: api::ChatRequest,
|
||||||
conversation_id: Option<Uuid>,
|
conversation_id: Option<Uuid>,
|
||||||
) -> Result<Response, (axum::http::StatusCode, String)> {
|
) -> Result<Response, ApiError> {
|
||||||
// Handle anonymous (API key) path early — no DB logging
|
// Handle anonymous (API key) path early — no DB logging
|
||||||
let Some(conv_id) = conversation_id else {
|
let Some(conv_id) = conversation_id else {
|
||||||
let stream = state
|
let stream = state.ollama.chat_completions_stream(&body).await?;
|
||||||
.ollama
|
|
||||||
.chat_completions_stream(&body)
|
|
||||||
.await
|
|
||||||
.map_err(into_http_response)?;
|
|
||||||
|
|
||||||
let plain_stream = stream.map(
|
let plain_stream = stream.map(
|
||||||
|item| -> Result<Event, crate::providers::ollama::errors::OllamaError> {
|
|item| -> Result<Event, crate::providers::ollama::errors::OllamaError> {
|
||||||
@@ -163,8 +158,7 @@ async fn handle_stream(
|
|||||||
.unwrap_or(""),
|
.unwrap_or(""),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
.map_err(errors::into_http_response)?;
|
|
||||||
|
|
||||||
let start_event = api::StreamEvent::Start(api::StartEventData {
|
let start_event = api::StreamEvent::Start(api::StartEventData {
|
||||||
conversation_id: conv_id,
|
conversation_id: conv_id,
|
||||||
@@ -275,12 +269,8 @@ async fn handle_non_stream(
|
|||||||
auth: Auth,
|
auth: Auth,
|
||||||
body: api::ChatRequest,
|
body: api::ChatRequest,
|
||||||
conversation_id: Option<Uuid>,
|
conversation_id: Option<Uuid>,
|
||||||
) -> Result<Response, (axum::http::StatusCode, String)> {
|
) -> Result<Response, ApiError> {
|
||||||
let mut response = state
|
let mut response = state.ollama.chat_completions(&body).await?;
|
||||||
.ollama
|
|
||||||
.chat_completions(&body)
|
|
||||||
.await
|
|
||||||
.map_err(into_http_response)?;
|
|
||||||
|
|
||||||
response.conversation_id = conversation_id;
|
response.conversation_id = conversation_id;
|
||||||
|
|
||||||
@@ -296,8 +286,7 @@ async fn handle_non_stream(
|
|||||||
.unwrap_or(""),
|
.unwrap_or(""),
|
||||||
response.usage.map(|u| u.prompt_tokens),
|
response.usage.map(|u| u.prompt_tokens),
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
.map_err(errors::into_http_response)?;
|
|
||||||
|
|
||||||
log_assistant_message(
|
log_assistant_message(
|
||||||
&state.postgres,
|
&state.postgres,
|
||||||
@@ -307,8 +296,7 @@ async fn handle_non_stream(
|
|||||||
&response.choices[0].message.content,
|
&response.choices[0].message.content,
|
||||||
response.usage.map(|u| u.completion_tokens),
|
response.usage.map(|u| u.completion_tokens),
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
.map_err(errors::into_http_response)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Json(response).into_response())
|
Ok(Json(response).into_response())
|
||||||
@@ -360,7 +348,7 @@ pub async fn chat_completions(
|
|||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
Extension(auth): Extension<Auth>,
|
Extension(auth): Extension<Auth>,
|
||||||
Json(mut body): Json<api::ChatRequest>,
|
Json(mut body): Json<api::ChatRequest>,
|
||||||
) -> Result<Response, (axum::http::StatusCode, String)> {
|
) -> Result<Response, ApiError> {
|
||||||
tracing::debug!("Received /chat/completion with body {:?}", body);
|
tracing::debug!("Received /chat/completion with body {:?}", body);
|
||||||
|
|
||||||
let conversation_id = if matches!(&auth, Auth::Jwt(_)) {
|
let conversation_id = if matches!(&auth, Auth::Jwt(_)) {
|
||||||
@@ -378,8 +366,7 @@ pub async fn chat_completions(
|
|||||||
depth as i64,
|
depth as i64,
|
||||||
None, // no cursor — fetch the most recent N messages
|
None, // no cursor — fetch the most recent N messages
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
.map_err(errors::into_http_response)?;
|
|
||||||
|
|
||||||
// Map MessageSummary → api::Message and prepend to the outgoing request
|
// Map MessageSummary → api::Message and prepend to the outgoing request
|
||||||
let history_messages: Vec<api::Message> = history
|
let history_messages: Vec<api::Message> = history
|
||||||
@@ -410,7 +397,7 @@ pub async fn chat_completions(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn generate_conversation_title(ollama: &OllamaProvider, first_message: &str) -> String {
|
async fn generate_conversation_title(ollama: &OllamaProvider, first_message: &str) -> String {
|
||||||
let request = CompletionRequest {
|
let request = api::CompletionRequest {
|
||||||
base: BaseLLMRequest {
|
base: BaseLLMRequest {
|
||||||
model: "llama3:latest".to_string(),
|
model: "llama3:latest".to_string(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -438,12 +425,12 @@ async fn log_user_message(
|
|||||||
content: &str,
|
content: &str,
|
||||||
tokens: Option<u32>,
|
tokens: Option<u32>,
|
||||||
) -> Result<Uuid, errors::DbError> {
|
) -> Result<Uuid, errors::DbError> {
|
||||||
chat::insert_message(
|
insert_message(
|
||||||
pool,
|
pool,
|
||||||
user_id,
|
user_id,
|
||||||
conversation_id,
|
conversation_id,
|
||||||
parent_id,
|
parent_id,
|
||||||
chat::MessageRole::User,
|
MessageRole::User,
|
||||||
content,
|
content,
|
||||||
tokens,
|
tokens,
|
||||||
)
|
)
|
||||||
@@ -458,12 +445,12 @@ async fn log_assistant_message(
|
|||||||
content: &str,
|
content: &str,
|
||||||
tokens: Option<u32>,
|
tokens: Option<u32>,
|
||||||
) -> Result<Uuid, errors::DbError> {
|
) -> Result<Uuid, errors::DbError> {
|
||||||
chat::insert_message(
|
insert_message(
|
||||||
pool,
|
pool,
|
||||||
user_id,
|
user_id,
|
||||||
conversation_id,
|
conversation_id,
|
||||||
Some(parent_id),
|
Some(parent_id),
|
||||||
chat::MessageRole::Assistant,
|
MessageRole::Assistant,
|
||||||
content,
|
content,
|
||||||
tokens,
|
tokens,
|
||||||
)
|
)
|
||||||
@@ -475,8 +462,7 @@ pub async fn get_conversations(
|
|||||||
State(state): State<AppState>,
|
State(state): State<AppState>,
|
||||||
Extension(auth): Extension<Auth>,
|
Extension(auth): Extension<Auth>,
|
||||||
Query(params): Query<api::ConversationQuery>,
|
Query(params): Query<api::ConversationQuery>,
|
||||||
) -> Result<Json<api::ConversationListResponse>, (axum::http::StatusCode, Json<api::ErrorResponse>)>
|
) -> Result<Json<api::ConversationListResponse>, ApiError> {
|
||||||
{
|
|
||||||
tracing::debug!("Conversation hit: {:?}", auth);
|
tracing::debug!("Conversation hit: {:?}", auth);
|
||||||
|
|
||||||
let conversations = get_conversations_entries(
|
let conversations = get_conversations_entries(
|
||||||
@@ -485,11 +471,7 @@ pub async fn get_conversations(
|
|||||||
params.limit.unwrap_or(20),
|
params.limit.unwrap_or(20),
|
||||||
params.before,
|
params.before,
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
.map_err(|e| {
|
|
||||||
let (code, msg) = errors::into_http_response(e);
|
|
||||||
(code, Json(api::ErrorResponse::new(msg)))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let has_more = conversations.len() == params.limit.unwrap_or(20) as usize;
|
let has_more = conversations.len() == params.limit.unwrap_or(20) as usize;
|
||||||
|
|
||||||
@@ -504,7 +486,7 @@ pub async fn get_messages(
|
|||||||
Extension(auth): Extension<Auth>,
|
Extension(auth): Extension<Auth>,
|
||||||
Path(conversation_id): Path<Uuid>,
|
Path(conversation_id): Path<Uuid>,
|
||||||
Query(params): Query<api::MessageQuery>,
|
Query(params): Query<api::MessageQuery>,
|
||||||
) -> Result<Json<api::MessageListResponse>, (axum::http::StatusCode, Json<api::ErrorResponse>)> {
|
) -> Result<Json<api::MessageListResponse>, ApiError> {
|
||||||
tracing::debug!("Messages hit: {:?}", auth);
|
tracing::debug!("Messages hit: {:?}", auth);
|
||||||
|
|
||||||
let messages = get_conversation_messages(
|
let messages = get_conversation_messages(
|
||||||
@@ -514,11 +496,7 @@ pub async fn get_messages(
|
|||||||
params.limit.unwrap_or(50),
|
params.limit.unwrap_or(50),
|
||||||
params.before,
|
params.before,
|
||||||
)
|
)
|
||||||
.await
|
.await?;
|
||||||
.map_err(|e| {
|
|
||||||
let (code, msg) = errors::into_http_response(e);
|
|
||||||
(code, Json(api::ErrorResponse::new(msg)))
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let has_more = messages.len() == params.limit.unwrap_or(50) as usize;
|
let has_more = messages.len() == params.limit.unwrap_or(50) as usize;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user