File size: 5,034 Bytes
12f8da0
 
 
 
 
 
 
 
 
 
 
 
 
89f930a
 
 
 
 
 
 
12f8da0
 
 
268147c
 
 
 
 
 
 
 
 
12f8da0
89f930a
 
 
 
12f8da0
 
 
89f930a
 
 
 
 
12f8da0
 
89f930a
 
 
 
12f8da0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89f930a
12f8da0
 
89f930a
12f8da0
 
 
89f930a
12f8da0
 
 
 
 
 
 
817f852
12f8da0
 
89f930a
12f8da0
 
 
268147c
 
 
 
 
 
 
 
 
12f8da0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import gradio as gr
import torch
import numpy as np
from PIL import Image
import os
import json
import base64
from io import BytesIO
import requests
from typing import Dict, List, Any, Optional
from transformers.pipelines import pipeline

# Initialize the model
try:
    model = pipeline("image-feature-extraction", model="nomic-ai/nomic-embed-vision-v1.5", trust_remote_code=True)
    model_loaded = True
except Exception as e:
    print(f"Error loading model: {str(e)}")
    model = None
    model_loaded = False

# Function to generate embeddings from an image
def generate_embedding(image):
    """
    Generate normalized embedding vector for the uploaded image.

    Args:
        image (PIL.Image.Image or np.ndarray): Input image uploaded by the user.

    Returns:
        list[float]: A normalized image embedding vector representing the input image.
    """
    if image is None:
        return {"error": "No image provided"}, "No image provided"
    
    if not model_loaded:
        return {"error": "Model not loaded properly"}, "Error: Model not loaded properly"
    
    # Convert to PIL Image if needed
    if not isinstance(image, Image.Image):
        try:
            image = Image.fromarray(image)
        except Exception as e:
            print(f"Error converting image: {str(e)}")
            return {"error": f"Invalid image format: {str(e)}"}, f"Error: Invalid image format"
    
    try:
        # Check if model is loaded before calling it
        if model is None:
            return {"error": "Model not loaded properly"}, "Error: Model not loaded properly"
            
        # Generate embedding using the transformers pipeline
        result = model(image)
        
        # Process the result based on its type
        embedding_list = None
        
        # Handle different possible output types
        if isinstance(result, torch.Tensor):
            embedding_list = result.detach().cpu().numpy().flatten().tolist()
        elif isinstance(result, np.ndarray):
            embedding_list = result.flatten().tolist()
        elif isinstance(result, list):
            # If it's a list of tensors or arrays
            if result and isinstance(result[0], (torch.Tensor, np.ndarray)):
                embedding_list = result[0].flatten().tolist() if hasattr(result[0], 'flatten') else result[0]
            else:
                embedding_list = result
        else:
            # Try to convert to a list as a last resort
            try:
                if result is not None:
                    embedding_list = list(result)
                else:
                    print("Result is None")
                    return {"error": "Failed to generate embedding"}, "Failed to generate embedding"
            except:
                print(f"Couldn't convert result of type {type(result)} to list")
                return {"error": "Failed to process embedding"}, "Failed to process embedding"
        
        # Ensure we have a valid embedding list
        if embedding_list is None:
            return {"error": "Failed to generate embedding"}, "Failed to generate embedding"
            
        # Calculate embedding dimension
        embedding_dim = len(embedding_list)
        
        return {
            "embedding": embedding_list,
            "dimension": embedding_dim
        }, f"Dimension: {embedding_dim}"
    except Exception as e:
        print(f"Error generating embedding: {str(e)}")
        return {"error": f"Error generating embedding: {str(e)}"}, f"Error: {str(e)}"

# Function to generate embeddings from an image URL
def embed_image_from_url(image_url):
    """
    Generate normalized embedding vector for the image from a URL.

    Args:
        image_url (str): Image URL provided by the User.

    Returns:
        list[float]: A normalized image embedding vector representing the input image.
    """
    try:
        # Download the image
        response = requests.get(image_url)
        image = Image.open(BytesIO(response.content))
        
        # Generate embedding
        return generate_embedding(image)
    except Exception as e:
        return {"error": str(e)}

# Function to generate embeddings from base64 image data
def embed_image_from_base64(image_data):
    try:
        # Decode the base64 image
        decoded_data = base64.b64decode(image_data)
        image = Image.open(BytesIO(decoded_data))
        
        # Generate embedding
        return generate_embedding(image)
    except Exception as e:
        return {"error": str(e)}

# Create a Gradio app
app = gr.Interface(
    fn=generate_embedding,
    inputs=gr.Image(type="pil", label="Input Image"),
    outputs=[
        gr.JSON(label="Embedding Output"),
        gr.Textbox(label="Embedding Dimension")
    ],
    title="Nomic Vision Embedding Model (nomic-ai/nomic-embed-vision-v1.5)",
    description="Upload an image to generate embeddings using the Nomic Vision model.",
    allow_flagging="never"
)

# Launch the app
if __name__ == "__main__":
    app.launch(mcp_server=True)