From 47a63afaef11a690af8f5554356e4322a59b90cc Mon Sep 17 00:00:00 2001 From: "yu.wang" Date: Tue, 24 Mar 2026 18:47:17 +0800 Subject: [PATCH 1/2] update readme --- README.md | 4 ++-- README_CN.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0f3d8fa..975e20b 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ A extreme lightweight SQLite Web administration tool based on Rust (Axum) and Solid.js. -- 🐳 **Extreme Lightweight**: Docker image size is only **~6.5MB**. -- ⚡ **High Performance**: Runtime memory usage is only **~700KB**. +- 🐳 **Extreme Lightweight**: Docker image size is only **~10MB**. +- ⚡ **High Performance**: Runtime memory usage is only **~1MB**. - 🤖 **AI Assistant**: Intelligently corrects wrong SQL, supports natural language to SQL conversion. ![screenshot](screenshot.png) diff --git a/README_CN.md b/README_CN.md index 5b2ffaf..4c73175 100644 --- a/README_CN.md +++ b/README_CN.md @@ -10,8 +10,8 @@ 基于 Rust (Axum) 和 Solid.js 的 **极致轻量** SQLite Web 管理工具。 -- 🐳 **极致轻量**: Docker 镜像大小仅 **~6.5MB**。 -- ⚡ **高性能**: 运行时内存占用仅 **~700KB**。 +- 🐳 **极致轻量**: Docker 镜像大小仅 **~10MB**。 +- ⚡ **高性能**: 运行时内存占用仅 **~1MB**。 - 🤖 **AI 辅助**: 智能纠正错误 SQL,支持自然语言转 SQL。 ![截图](screenshot.png) From e214f127dcaa583a166b3c36ba00907bb250cc2d Mon Sep 17 00:00:00 2001 From: "yu.wang" Date: Sun, 29 Mar 2026 12:18:54 +0800 Subject: [PATCH 2/2] feat: prompt add show version --- README.md | 2 +- README_CN.md | 2 +- backend/Cargo.toml | 2 +- backend/src/handlers/ai.rs | 38 +++++++++++++++++++++++++----- frontend/src/components/Navbar.tsx | 14 +++++++++-- frontend/src/lib/api.ts | 10 ++++++++ 6 files changed, 57 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 975e20b..b673318 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ services: | RUST_LOG | `rust_sqlite_webui=debug,tower_http=debug` | Logging level configuration. | | OPENAI_API_KEY | - | OpenAI API key (required for AI assistant). | | OPENAI_BASE_URL | `https://api.openai.com/v1` | OpenAI API base URL. | -| OPENAI_MODEL | `gpt-3.5-turbo` | OpenAI model name. | +| OPENAI_MODEL | `gpt-5.4-mini` | OpenAI model name. | > **Tip**: For development, create a `.env` file in `backend/` directory to configure these variables. diff --git a/README_CN.md b/README_CN.md index 4c73175..84ed36e 100644 --- a/README_CN.md +++ b/README_CN.md @@ -62,7 +62,7 @@ services: | RUST_LOG | `rust_sqlite_webui=debug,tower_http=debug` | 日志级别配置。| | OPENAI_API_KEY | - | OpenAI API 密钥(AI 辅助功能必需)。| | OPENAI_BASE_URL | `https://api.openai.com/v1` | OpenAI API 地址。| -| OPENAI_MODEL | `gpt-3.5-turbo` | OpenAI 模型名称。| +| OPENAI_MODEL | `gpt-5.4-mini` | OpenAI 模型名称。| > **提示**: 开发环境下可在 `backend/` 目录创建 `.env` 文件配置上述变量。 diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 14abb39..a856792 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rust-sqlite-webui" -version = "0.2.0" +version = "0.2.1" edition = "2024" [dependencies] diff --git a/backend/src/handlers/ai.rs b/backend/src/handlers/ai.rs index c6b6df1..a58f929 100644 --- a/backend/src/handlers/ai.rs +++ b/backend/src/handlers/ai.rs @@ -26,7 +26,7 @@ pub async fn correct_sql( ) -> impl IntoResponse { let api_key = std::env::var("OPENAI_API_KEY"); let base_url = std::env::var("OPENAI_BASE_URL").unwrap_or_else(|_| "https://api.openai.com/v1".to_string()); - let model = std::env::var("OPENAI_MODEL").unwrap_or_else(|_| "gpt-3.5-turbo".to_string()); + let model = std::env::var("OPENAI_MODEL").unwrap_or_else(|_| "gpt-5.4-mini".to_string()); if api_key.is_err() { return Json(CorrectResponse { @@ -55,7 +55,7 @@ pub async fn correct_sql( let mut schema_str = String::new(); for (name, col_type, not_null, pk) in &columns { - schema_str.push_str(&format!(" {} {}", col_type, name)); + schema_str.push_str(&format!(" {} {}",name, col_type)); if *pk { schema_str.push_str(" PRIMARY KEY"); } if *not_null { schema_str.push_str(" NOT NULL"); } schema_str.push('\n'); @@ -63,6 +63,32 @@ pub async fn correct_sql( for (from, to_table, to_col) in &foreign_keys { schema_str.push_str(&format!(" {} REFERENCES {}({})\n", from, to_table, to_col)); } + // try to fetch one sample row from the table + let sample_row = sqlx::query(&format!("SELECT * FROM {} LIMIT 1", payload.table)) + .fetch_optional(pool) + .await + .ok() + .flatten(); + + let mut sample_str = String::new(); + if let Some(row) = sample_row { + let mut parts: Vec = Vec::new(); + for (name, _col_type, _not_null, _pk) in &columns { + // try several common types and fall back to NULL + let val = row.try_get::(name) + .map(|s| s) + .or_else(|_| row.try_get::(name).map(|v| v.to_string())) + .or_else(|_| row.try_get::(name).map(|v| v.to_string())) + .unwrap_or_else(|_| "NULL".to_string()); + parts.push(format!("{}={}", name, val)); + } + sample_str = parts.join(", "); + } + + // append sample row info to schema string for prompt clarity + if !sample_str.is_empty() { + schema_str.push_str(&format!("\nSample row: {}\n", sample_str)); + } schema_str } else { String::new() @@ -71,11 +97,11 @@ pub async fn correct_sql( let client = Client::new(); let prompt = format!( - "Correct the following SQL using SQLite dialect.\n\ + "Correct/Translate/Complete the User Input to SQL using SQLite dialect.\n\ Table: {}\n\ Schema:\n{}\n\ - SQL: {}\n\n\ - if you have no idea just return a basic query that can run.", + User Input: {}\n\n\ + If user intent is ambiguous, return a simple SELECT * FROM LIMIT 10.", payload.table, schema, payload.sql ); tracing::debug!("AI API prompt: {}", prompt); @@ -85,7 +111,7 @@ pub async fn correct_sql( .json(&json!({ "model": model, "messages": [ - {"role": "system", "content": "You are a helpful SQL expert assistant. Always return raw SQL string without any format."}, + {"role": "system", "content": "You are a SQL expert. Always reply a single raw SQL string without any format."}, {"role": "user", "content": prompt} ], "reasoning_effort": "low" diff --git a/frontend/src/components/Navbar.tsx b/frontend/src/components/Navbar.tsx index cc4e9e6..5d339a6 100644 --- a/frontend/src/components/Navbar.tsx +++ b/frontend/src/components/Navbar.tsx @@ -1,9 +1,10 @@ import { Component, createSignal, onMount, For, Show } from "solid-js"; import ThemeSwitch from "./ThemeSwitch"; import { fetchTables, resetStore, apiKey, setIsAuthModalOpen } from "../lib/store"; -import { getDbFiles, connectDb } from "../lib/api"; +import { getDbFiles, connectDb, getHealth } from "../lib/api"; const Navbar: Component = () => { + const [appVersion, setAppVersion] = createSignal(""); // DB Logic const [dbFiles, setDbFiles] = createSignal([]); const [currentPath, setCurrentPath] = createSignal(""); @@ -15,6 +16,10 @@ const Navbar: Component = () => { onMount(async () => { // DB Auto-load Logic await fetchDbFiles(); + + // fetch version from health endpoint + const h = await getHealth(); + setAppVersion(h.version || ""); }); async function fetchDbFiles() { @@ -143,7 +148,12 @@ const Navbar: Component = () => {