add-about #7

Open
godber wants to merge 4 commits from add-about into main
14 changed files with 199 additions and 16 deletions
Showing only changes of commit 2f458884a2 - Show all commits

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Austin Godber - EmbeddingBuddy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,6 +1,6 @@
[project] [project]
name = "embeddingbuddy" name = "embeddingbuddy"
version = "0.5.1" version = "0.6.0"
description = "A Python Dash application for interactive exploration and visualization of embedding vectors through dimensionality reduction techniques." description = "A Python Dash application for interactive exploration and visualization of embedding vectors through dimensionality reduction techniques."
readme = "README.md" readme = "README.md"
requires-python = ">=3.11" requires-python = ">=3.11"

View File

@@ -12,9 +12,15 @@ def main():
os.environ["EMBEDDINGBUDDY_ENV"] = "development" os.environ["EMBEDDINGBUDDY_ENV"] = "development"
os.environ["EMBEDDINGBUDDY_DEBUG"] = "true" os.environ["EMBEDDINGBUDDY_DEBUG"] = "true"
# Check for OpenSearch disable flag (optional for testing)
# Set EMBEDDINGBUDDY_OPENSEARCH_ENABLED=false to test without OpenSearch
opensearch_status = os.getenv("EMBEDDINGBUDDY_OPENSEARCH_ENABLED", "true")
opensearch_enabled = opensearch_status.lower() == "true"
print("🚀 Starting EmbeddingBuddy in development mode...") print("🚀 Starting EmbeddingBuddy in development mode...")
print("📁 Auto-reload enabled - changes will trigger restart") print("📁 Auto-reload enabled - changes will trigger restart")
print("🌐 Server will be available at http://127.0.0.1:8050") print("🌐 Server will be available at http://127.0.0.1:8050")
print(f"🔍 OpenSearch: {'Enabled' if opensearch_enabled else 'Disabled'}")
print("⏹️ Press Ctrl+C to stop") print("⏹️ Press Ctrl+C to stop")
app = create_app() app = create_app()

View File

@@ -13,6 +13,9 @@ def main():
# Force production settings # Force production settings
os.environ["EMBEDDINGBUDDY_ENV"] = "production" os.environ["EMBEDDINGBUDDY_ENV"] = "production"
os.environ["EMBEDDINGBUDDY_DEBUG"] = "false" os.environ["EMBEDDINGBUDDY_DEBUG"] = "false"
# Disable OpenSearch by default in production (can be overridden by setting env var)
if "EMBEDDINGBUDDY_OPENSEARCH_ENABLED" not in os.environ:
os.environ["EMBEDDINGBUDDY_OPENSEARCH_ENABLED"] = "false"
print("🚀 Starting EmbeddingBuddy in production mode...") print("🚀 Starting EmbeddingBuddy in production mode...")
print(f"⚙️ Workers: {AppSettings.GUNICORN_WORKERS}") print(f"⚙️ Workers: {AppSettings.GUNICORN_WORKERS}")

View File

@@ -85,6 +85,9 @@ class AppSettings:
GUNICORN_KEEPALIVE = int(os.getenv("GUNICORN_KEEPALIVE", "5")) GUNICORN_KEEPALIVE = int(os.getenv("GUNICORN_KEEPALIVE", "5"))
# OpenSearch Configuration # OpenSearch Configuration
OPENSEARCH_ENABLED = (
os.getenv("EMBEDDINGBUDDY_OPENSEARCH_ENABLED", "True").lower() == "true"
)
OPENSEARCH_DEFAULT_SIZE = 100 OPENSEARCH_DEFAULT_SIZE = 100
OPENSEARCH_SAMPLE_SIZE = 5 OPENSEARCH_SAMPLE_SIZE = 5
OPENSEARCH_CONNECTION_TIMEOUT = 30 OPENSEARCH_CONNECTION_TIMEOUT = 30

View File

@@ -82,19 +82,23 @@ class DataProcessingCallbacks:
) )
def render_tab_content(active_tab): def render_tab_content(active_tab):
from ...ui.components.datasource import DataSourceComponent from ...ui.components.datasource import DataSourceComponent
from ...config.settings import AppSettings
datasource = DataSourceComponent() datasource = DataSourceComponent()
if active_tab == "opensearch-tab": if active_tab == "opensearch-tab" and AppSettings.OPENSEARCH_ENABLED:
return [datasource.create_opensearch_tab()] return [datasource.create_opensearch_tab()]
elif active_tab == "text-input-tab": elif active_tab == "text-input-tab":
return [datasource.create_text_input_tab()] return [datasource.create_text_input_tab()]
else: else:
return [datasource.create_file_upload_tab()] return [datasource.create_file_upload_tab()]
# Register callbacks for both data and prompts sections # Register callbacks for both data and prompts sections (only if OpenSearch is enabled)
self._register_opensearch_callbacks("data", self.opensearch_client_data) if AppSettings.OPENSEARCH_ENABLED:
self._register_opensearch_callbacks("prompts", self.opensearch_client_prompts) self._register_opensearch_callbacks("data", self.opensearch_client_data)
self._register_opensearch_callbacks(
"prompts", self.opensearch_client_prompts
)
# Register collapsible section callbacks # Register collapsible section callbacks
self._register_collapse_callbacks() self._register_collapse_callbacks()

View File

@@ -5,9 +5,31 @@ import dash_bootstrap_components as dbc
class AboutComponent: class AboutComponent:
def _get_about_content(self): def _get_about_content(self):
return """ return """
# 🔍 Interactive Embedding Visualization # 🔍 Interactive Embedding Vector Visualization
EmbeddingBuddy is a web application for interactive exploration and
visualization of embedding vectors through dimensionality reduction techniques
(PCA, t-SNE, UMAP).
You have two ways to get started:
1. Generate embeddings directly in the browser if it supports WebGPU.
2. Upload your NDJSON file containing embedding vectors and metadata.
## Generating Embeddings in Browser
1. Expand the "Generate Embeddings" section.
2. Input your text data (one entry per line).
1. Optionally you can use the built in sample data by clicking "Load Sample Data" button.
3. Click "Generate Embeddings" to create vectors using a pre-trained model.
## NDJSON File Format
```json
{"id": "doc_001", "embedding": [0.1, -0.3, 0.7, ...], "text": "Sample text content", "category": "news", "subcategory": "politics", "tags": ["election", "politics"]}
{"id": "doc_002", "embedding": [0.2, -0.1, 0.9, ...], "text": "Another example", "category": "review", "subcategory": "product", "tags": ["tech", "gadget"]}
```
EmbeddingBuddy is a modular Python Dash web application for interactive exploration and visualization of embedding vectors through dimensionality reduction techniques (PCA, t-SNE, UMAP).
## ✨ Features ## ✨ Features
@@ -35,7 +57,7 @@ EmbeddingBuddy is a modular Python Dash web application for interactive explorat
return dbc.Modal( return dbc.Modal(
[ [
dbc.ModalHeader( dbc.ModalHeader(
dbc.ModalTitle("About EmbeddingBuddy"), dbc.ModalTitle("Welcome to EmbeddingBuddy"),
close_button=True, close_button=True,
), ),
dbc.ModalBody( dbc.ModalBody(
@@ -53,7 +75,7 @@ EmbeddingBuddy is a modular Python Dash web application for interactive explorat
), ),
], ],
id="about-modal", id="about-modal",
is_open=False, is_open=True,
size="lg", size="lg",
) )

View File

@@ -1,6 +1,7 @@
from dash import dcc, html from dash import dcc, html
import dash_bootstrap_components as dbc import dash_bootstrap_components as dbc
from .upload import UploadComponent from .upload import UploadComponent
from embeddingbuddy.config.settings import AppSettings
class DataSourceComponent: class DataSourceComponent:
@@ -9,15 +10,18 @@ class DataSourceComponent:
def create_tabbed_interface(self): def create_tabbed_interface(self):
"""Create tabbed interface for different data sources.""" """Create tabbed interface for different data sources."""
tabs = [dbc.Tab(label="File Upload", tab_id="file-tab")]
# Only add OpenSearch tab if enabled
if AppSettings.OPENSEARCH_ENABLED:
tabs.append(dbc.Tab(label="OpenSearch", tab_id="opensearch-tab"))
return dbc.Card( return dbc.Card(
[ [
dbc.CardHeader( dbc.CardHeader(
[ [
dbc.Tabs( dbc.Tabs(
[ tabs,
dbc.Tab(label="File Upload", tab_id="file-tab"),
dbc.Tab(label="OpenSearch", tab_id="opensearch-tab"),
],
id="data-source-tabs", id="data-source-tabs",
active_tab="file-tab", active_tab="file-tab",
) )

View File

@@ -3,6 +3,7 @@ import dash_bootstrap_components as dbc
from .upload import UploadComponent from .upload import UploadComponent
from .datasource import DataSourceComponent from .datasource import DataSourceComponent
from .textinput import TextInputComponent from .textinput import TextInputComponent
from embeddingbuddy.config.settings import AppSettings
class SidebarComponent: class SidebarComponent:
@@ -102,6 +103,10 @@ class SidebarComponent:
) )
def _create_data_sources_item(self): def _create_data_sources_item(self):
tooltip_text = "Load existing embeddings: upload files"
if AppSettings.OPENSEARCH_ENABLED:
tooltip_text += " or read from OpenSearch"
return dbc.AccordionItem( return dbc.AccordionItem(
[ [
self.datasource_component.create_error_alert(), self.datasource_component.create_error_alert(),
@@ -115,7 +120,7 @@ class SidebarComponent:
className="fas fa-info-circle text-muted", className="fas fa-info-circle text-muted",
style={"cursor": "pointer"}, style={"cursor": "pointer"},
id="load-embeddings-info-icon", id="load-embeddings-info-icon",
title="Load existing embeddings: upload files or read from OpenSearch", title=tooltip_text,
), ),
] ]
), ),

View File

@@ -16,14 +16,14 @@ class TextInputComponent:
"""Create the complete text input interface with model selection and processing options.""" """Create the complete text input interface with model selection and processing options."""
return html.Div( return html.Div(
[ [
# Model selection section
self._create_model_selection(),
html.Hr(),
# Text input section # Text input section
self._create_text_input_area(), self._create_text_input_area(),
# Text action buttons # Text action buttons
self._create_text_action_buttons(), self._create_text_action_buttons(),
html.Hr(), html.Hr(),
# Model selection section
self._create_model_selection(),
html.Hr(),
# Processing options # Processing options
self._create_processing_options(), self._create_processing_options(),
html.Hr(), html.Hr(),