File size: 5,696 Bytes
e8f9d10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1dc5abe
e8f9d10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95ff73d
e8f9d10
 
 
 
 
 
 
 
95ff73d
 
 
 
 
 
e8f9d10
95ff73d
e8f9d10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# filename: __init__.py

"""
LightweightEmbeddings - FastAPI Application Entry Point

This application provides text and image embeddings using multiple text models and one image model.

Supported text model IDs:
- "multilingual-e5-small"
- "paraphrase-multilingual-MiniLM-L12-v2"
- "bge-m3"

Supported image model ID:
- "google/siglip-base-patch16-256-multilingual"
"""

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import gradio as gr
import requests
import json
from gradio.routes import mount_gradio_app

# Application metadata
__version__ = "1.0.0"
__author__ = "lamhieu"
__description__ = "Fast, lightweight, multilingual embeddings solution."

# Set your embeddings API URL here (change host/port if needed)
EMBEDDINGS_API_URL = "http://localhost:7860/v1/embeddings"

# Initialize FastAPI application
app = FastAPI(
    title="Lightweight Embeddings API",
    description=__description__,
    version=__version__,
    docs_url="/docs",
    redoc_url="/redoc",
)

# Configure CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],  # Adjust if needed for specific domains
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Include your existing router (which provides /v1/embeddings, /v1/rank, etc.)
from .router import router

app.include_router(router, prefix="/v1")


def call_embeddings_api(user_input: str, selected_model: str) -> str:
    """
    Send a request to the /v1/embeddings endpoint with the given model and input.
    Return a pretty-printed JSON response or an error message.
    """
    payload = {
        "model": selected_model,
        "input": user_input,
    }
    headers = {"Content-Type": "application/json"}

    try:
        response = requests.post(
            EMBEDDINGS_API_URL, json=payload, headers=headers, timeout=20
        )
    except requests.exceptions.RequestException as e:
        return f"❌ Network Error: {str(e)}"

    if response.status_code != 200:
        # Provide detailed error message
        return f"❌ API Error {response.status_code}: {response.text}"

    try:
        data = response.json()
        return json.dumps(data, indent=2)
    except ValueError:
        return "❌ Failed to parse JSON from API response."


def create_main_interface():
    """
    Creates a Gradio Blocks interface showing project info and an embeddings playground.
    """
    # Metadata to be displayed
    root_data = {
        "project": "Lightweight Embeddings Service",
        "version": "1.0.0",
        "description": (
            "Fast and efficient multilingual text and image embeddings service "
            "powered by sentence-transformers, supporting 100+ languages and multi-modal inputs"
        ),
        "docs": "https://lamhieu-lightweight-embeddings.hf.space/docs",
        "github": "https://github.com/lh0x00/lightweight-embeddings",
        "spaces": "https://huggingface.co/spaces/lamhieu/lightweight-embeddings",
    }

    # Available model options for the dropdown
    model_options = [
        "multilingual-e5-small",
        "paraphrase-multilingual-MiniLM-L12-v2",
        "bge-m3",
        "google/siglip-base-patch16-256-multilingual",
    ]

    with gr.Blocks(title="Lightweight Embeddings", theme="default") as demo:
        # Project Info
        gr.Markdown(
            """
            ## πŸš€ **Lightweight Embeddings** 
            
            Welcome to the **Lightweight Embeddings** API, a blazing-fast and flexible service 
            supporting **text** and **image** embeddings. Below you'll find key project details:
            """
        )
        gr.Markdown(
            f"""
            ---
            ### πŸ“¦ Project Details
            - **Description**: {root_data["description"]}
            
            ### πŸ”— Links
            - [Documentation]({root_data["docs"]}) | [GitHub]({root_data["github"]}) | [Demo]({root_data["spaces"]})

            ### πŸ’‘ How to Use
            Visit **/docs** for API documentation or try the playground below! 🌏
            """
        )

        # Embeddings Playground
        with gr.Accordion("πŸ”¬ Try the Embeddings Playground", open=True):
            gr.Markdown(
                "Enter your **text** or an **image URL**, pick a model, "
                "then click **Generate** to get embeddings from the `/v1/embeddings` API."
            )
            input_text = gr.Textbox(
                label="Input Text or Image URL",
                placeholder="Type some text or paste an image URL...",
                lines=3,
            )
            model_dropdown = gr.Dropdown(
                choices=model_options,
                value=model_options[0],
                label="Select Model",
            )
            generate_btn = gr.Button("Generate Embeddings")
            output_json = gr.Textbox(
                label="Embeddings API Response",
                lines=15,
                interactive=False,
            )

            # Link the button to the inference function
            generate_btn.click(
                fn=call_embeddings_api,
                inputs=[input_text, model_dropdown],
                outputs=output_json,
            )

    return demo


# Create and mount the Gradio Blocks at the root path
main_interface = create_main_interface()
mount_gradio_app(app, main_interface, path="/")


# Startup and shutdown events
@app.on_event("startup")
async def startup_event():
    """
    Initialize resources (like model loading) when the application starts.
    """
    pass


@app.on_event("shutdown")
async def shutdown_event():
    """
    Perform cleanup before the application shuts down.
    """
    pass