mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-05 17:09:40 +00:00
Add component to read PDF files into assistants (#439)
Build and Release / Read metadata (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage deb updater) (push) Has been cancelled
Build and Release / Prepare & create release (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage deb updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (push) Has been cancelled
Build and Release / Publish release (push) Has been cancelled
Build and Release / Read metadata (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage deb updater) (push) Has been cancelled
Build and Release / Prepare & create release (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage deb updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Has been cancelled
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (push) Has been cancelled
Build and Release / Publish release (push) Has been cancelled
This commit is contained in:
1 parent
9996b810e2
commit
c4d9af18cd
38 files changed
+661
-119
No files matched your search
@@ -7,13 +7,14 @@ use rocket::serde::json::Json;
|
||||
use rocket::serde::Serialize;
|
||||
use serde::Deserialize;
|
||||
use tauri::updater::UpdateResponse;
|
||||
use tauri::{Manager, Window};
|
||||
use tauri::{Manager, PathResolver, Window};
|
||||
use tauri::api::dialog::blocking::FileDialogBuilder;
|
||||
use tokio::time;
|
||||
use crate::api_token::APIToken;
|
||||
use crate::dotnet::stop_dotnet_server;
|
||||
use crate::environment::{is_prod, CONFIG_DIRECTORY, DATA_DIRECTORY};
|
||||
use crate::log::switch_to_file_logging;
|
||||
use crate::metadata::META_DATA;
|
||||
|
||||
/// The Tauri main window.
|
||||
static MAIN_WINDOW: Lazy<Mutex<Option<Window>>> = Lazy::new(|| Mutex::new(None));
|
||||
@@ -39,6 +40,7 @@ pub fn start_tauri() {
|
||||
info!(Source = "Bootloader Tauri"; "Reconfigure the file logger to use the app data directory {data_path:?}");
|
||||
switch_to_file_logging(data_path).map_err(|e| error!("Failed to switch logging to file: {e}")).unwrap();
|
||||
|
||||
deploy_pdfium(app.path_resolver());
|
||||
Ok(())
|
||||
})
|
||||
.plugin(tauri_plugin_window_state::Builder::default().build())
|
||||
@@ -319,4 +321,50 @@ pub struct PreviousFile {
|
||||
pub struct FileSelectionResponse {
|
||||
user_cancelled: bool,
|
||||
selected_file_path: String,
|
||||
}
|
||||
|
||||
fn deploy_pdfium(path_resolver: PathResolver) {
|
||||
info!(Source = "Bootloader Tauri"; "Deploy PDFium from the resources...");
|
||||
let working_directory = std::env::current_dir().unwrap();
|
||||
let pdfium_target_path = working_directory;
|
||||
let metadata = &META_DATA;
|
||||
let metadata = metadata.lock().unwrap();
|
||||
let arch = metadata.clone().unwrap().architecture;
|
||||
let pdfium_filename = match arch.as_str() {
|
||||
"linux-x64" => Some("libpdfium.so"),
|
||||
"linux-arm64" => Some("libpdfium.so"),
|
||||
|
||||
"win-x64" => Some("pdfium.dll"),
|
||||
"win-arm64" => Some("pdfium.dll"),
|
||||
|
||||
"osx-x64" => Some("libpdfium.dylib"),
|
||||
"osx-arm64" => Some("libpdfium.dylib"),
|
||||
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if pdfium_filename.is_none() {
|
||||
error!(Source = "Bootloader Tauri"; "Failed to find the PDFium library for the current platform.");
|
||||
return;
|
||||
}
|
||||
|
||||
let pdfium_filename = pdfium_filename.unwrap();
|
||||
let pdfium_relative_source_path = String::from("resources/libraries/") + pdfium_filename;
|
||||
let pdfium_source_path = path_resolver.resolve_resource(pdfium_relative_source_path);
|
||||
if pdfium_source_path.is_none() {
|
||||
error!(Source = "Bootloader Tauri"; "Failed to find the PDFium library for the current platform.");
|
||||
return;
|
||||
}
|
||||
|
||||
let pdfium_source_path = pdfium_source_path.unwrap();
|
||||
let pdfium_target_path = pdfium_target_path.join(pdfium_filename);
|
||||
|
||||
info!(Source = "Bootloader Tauri"; "Detected platform: {arch:?}, expected PDFium filename: {pdfium_filename:?}, source path: {pdfium_source_path:?}, target path: {pdfium_target_path:?}");
|
||||
|
||||
if let Err(e) = std::fs::copy(pdfium_source_path, pdfium_target_path) {
|
||||
error!(Source = "Bootloader Tauri"; "Failed to copy the PDFium library for the current platform: {e}");
|
||||
return;
|
||||
}
|
||||
|
||||
info!(Source = "Bootloader Tauri"; "Successfully deployed PDFium.");
|
||||
}
|
||||
@@ -15,6 +15,7 @@ use rocket::response::stream::{EventStream, Event};
|
||||
use rocket::tokio::select;
|
||||
use rocket::serde::Serialize;
|
||||
use rocket::get;
|
||||
use crate::api_token::APIToken;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct Chunk {
|
||||
@@ -39,7 +40,7 @@ type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>
|
||||
type ChunkStream = Pin<Box<dyn Stream<Item = Result<Chunk>> + Send>>;
|
||||
|
||||
#[get("/retrieval/fs/extract?<path>")]
|
||||
pub async fn extract_data(path: String, mut end: Shutdown) -> EventStream![] {
|
||||
pub async fn extract_data(_token: APIToken, path: String, mut end: Shutdown) -> EventStream![] {
|
||||
EventStream! {
|
||||
let stream_result = stream_data(&path).await;
|
||||
match stream_result {
|
||||
@@ -78,7 +79,7 @@ async fn stream_data(file_path: &str) -> Result<ChunkStream> {
|
||||
FileFormat::from_file(&file_path_clone)
|
||||
}).await??;
|
||||
|
||||
let ext = file_path.split('.').last().unwrap_or("");
|
||||
let ext = file_path.split('.').next_back().unwrap_or("");
|
||||
let stream = match ext {
|
||||
DOCX | ODT => {
|
||||
let from = if ext == DOCX { "docx" } else { "odt" };
|
||||
@@ -91,7 +92,7 @@ async fn stream_data(file_path: &str) -> Result<ChunkStream> {
|
||||
|
||||
_ => match fmt.kind() {
|
||||
Kind::Document => match fmt {
|
||||
FileFormat::PortableDocumentFormat => read_pdf(file_path).await?,
|
||||
FileFormat::PortableDocumentFormat => stream_pdf(file_path).await?,
|
||||
FileFormat::MicrosoftWordDocument => {
|
||||
convert_with_pandoc(file_path, "docx", TO_MARKDOWN).await?
|
||||
}
|
||||
@@ -133,7 +134,7 @@ async fn stream_text_file(file_path: &str) -> Result<ChunkStream> {
|
||||
let mut line_number = 0;
|
||||
|
||||
let stream = stream! {
|
||||
while let Ok(Some(line)) = lines.next_line().await { // Korrektur hier
|
||||
while let Ok(Some(line)) = lines.next_line().await {
|
||||
line_number += 1;
|
||||
yield Ok(Chunk {
|
||||
content: line,
|
||||
@@ -145,23 +146,47 @@ async fn stream_text_file(file_path: &str) -> Result<ChunkStream> {
|
||||
Ok(Box::pin(stream))
|
||||
}
|
||||
|
||||
async fn read_pdf(file_path: &str) -> Result<ChunkStream> {
|
||||
#[get("/retrieval/fs/read/pdf?<file_path>")]
|
||||
pub fn read_pdf(_token: APIToken, file_path: String) -> String {
|
||||
let pdfium = Pdfium::default();
|
||||
let doc = match pdfium.load_pdf_from_file(&file_path, None) {
|
||||
Ok(document) => document,
|
||||
Err(e) => return e.to_string(),
|
||||
};
|
||||
|
||||
let mut pdf_content = String::new();
|
||||
for page in doc.pages().iter() {
|
||||
let content = match page.text().map(|text_content| text_content.all()) {
|
||||
Ok(content) => content,
|
||||
Err(_) => {
|
||||
continue
|
||||
}
|
||||
};
|
||||
|
||||
pdf_content.push_str(&content);
|
||||
pdf_content.push_str("\n\n");
|
||||
}
|
||||
|
||||
pdf_content
|
||||
}
|
||||
|
||||
async fn stream_pdf(file_path: &str) -> Result<ChunkStream> {
|
||||
let path = file_path.to_owned();
|
||||
let (tx, rx) = mpsc::channel(10);
|
||||
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let pdfium = Pdfium::default();
|
||||
let doc = match pdfium.load_pdf_from_file(&path, None) {
|
||||
Ok(d) => d,
|
||||
Ok(document) => document,
|
||||
Err(e) => {
|
||||
let _ = tx.blocking_send(Err(e.into()));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
for (i, page) in doc.pages().iter().enumerate() {
|
||||
for (num_page, page) in doc.pages().iter().enumerate() {
|
||||
let content = match page.text().map(|t| t.all()) {
|
||||
Ok(c) => c,
|
||||
Ok(text_content) => text_content,
|
||||
Err(e) => {
|
||||
let _ = tx.blocking_send(Err(e.into()));
|
||||
continue;
|
||||
@@ -170,7 +195,7 @@ async fn read_pdf(file_path: &str) -> Result<ChunkStream> {
|
||||
|
||||
if tx.blocking_send(Ok(Chunk {
|
||||
content,
|
||||
metadata: Metadata::Pdf { page_number: i + 1 },
|
||||
metadata: Metadata::Pdf { page_number: num_page + 1 },
|
||||
})).is_err() {
|
||||
break;
|
||||
}
|
||||
|
||||
+2
-1
@@ -9,4 +9,5 @@ pub mod secret;
|
||||
pub mod clipboard;
|
||||
pub mod runtime_api;
|
||||
pub mod certificate;
|
||||
pub mod file_data;
|
||||
pub mod file_data;
|
||||
pub mod metadata;
|
||||
@@ -10,6 +10,7 @@ use mindwork_ai_studio::certificate::{generate_certificate};
|
||||
use mindwork_ai_studio::dotnet::start_dotnet_server;
|
||||
use mindwork_ai_studio::environment::is_dev;
|
||||
use mindwork_ai_studio::log::init_logging;
|
||||
use mindwork_ai_studio::metadata::{MetaData, META_DATA};
|
||||
use mindwork_ai_studio::runtime_api::start_runtime_api;
|
||||
|
||||
#[tokio::main]
|
||||
@@ -26,6 +27,22 @@ async fn main() {
|
||||
let tauri_version = metadata_lines.next().unwrap();
|
||||
let app_commit_hash = metadata_lines.next().unwrap();
|
||||
let architecture = metadata_lines.next().unwrap();
|
||||
let pdfium_version = metadata_lines.next().unwrap();
|
||||
|
||||
let metadata = MetaData {
|
||||
architecture: architecture.to_string(),
|
||||
app_commit_hash: app_commit_hash.to_string(),
|
||||
app_version: app_version.to_string(),
|
||||
build_number: build_number.to_string(),
|
||||
build_time: build_time.to_string(),
|
||||
dotnet_sdk_version: dotnet_sdk_version.to_string(),
|
||||
dotnet_version: dotnet_version.to_string(),
|
||||
mud_blazor_version: mud_blazor_version.to_string(),
|
||||
rust_version: rust_version.to_string(),
|
||||
tauri_version: tauri_version.to_string(),
|
||||
};
|
||||
|
||||
*META_DATA.lock().unwrap() = Some(metadata);
|
||||
|
||||
init_logging();
|
||||
info!("Starting MindWork AI Studio:");
|
||||
@@ -40,6 +57,7 @@ async fn main() {
|
||||
info!(".. Rust: v{rust_version}");
|
||||
info!(".. MudBlazor: v{mud_blazor_version}");
|
||||
info!(".. Tauri: v{tauri_version}");
|
||||
info!(".. PDFium: v{pdfium_version}");
|
||||
|
||||
if is_dev() {
|
||||
warn!("Running in development mode.");
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
use std::sync::Mutex;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
pub static META_DATA: Lazy<Mutex<Option<MetaData>>> = Lazy::new(|| Mutex::new(None));
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct MetaData {
|
||||
pub app_version: String,
|
||||
pub build_time: String,
|
||||
pub build_number: String,
|
||||
pub dotnet_sdk_version: String,
|
||||
pub dotnet_version: String,
|
||||
pub rust_version: String,
|
||||
pub mud_blazor_version: String,
|
||||
pub tauri_version: String,
|
||||
pub app_commit_hash: String,
|
||||
pub architecture: String,
|
||||
}
|
||||
@@ -79,6 +79,7 @@ pub fn start_runtime_api() {
|
||||
crate::environment::get_config_directory,
|
||||
crate::environment::read_user_language,
|
||||
crate::file_data::extract_data,
|
||||
crate::file_data::read_pdf,
|
||||
crate::log::get_log_paths,
|
||||
])
|
||||
.ignite().await.unwrap()
|
||||
|
||||
Reference in new issue
Block a user