mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-08 03:08:45 +00:00
init ui for bedrock s3 vectors
This commit is contained in:
parent
7aa11ecf4a
commit
fc4a484cb1
6 changed files with 611 additions and 5 deletions
|
|
@ -6954,7 +6954,8 @@ export const ragIngestCall = async (
|
|||
customLlmProvider: string,
|
||||
vectorStoreId?: string,
|
||||
vectorStoreName?: string,
|
||||
vectorStoreDescription?: string
|
||||
vectorStoreDescription?: string,
|
||||
providerSpecificParams?: Record<string, any>
|
||||
): Promise<any> => {
|
||||
try {
|
||||
let url = proxyBaseUrl ? `${proxyBaseUrl}/rag/ingest` : `/rag/ingest`;
|
||||
|
|
@ -6967,6 +6968,7 @@ export const ragIngestCall = async (
|
|||
vector_store: {
|
||||
custom_llm_provider: customLlmProvider,
|
||||
...(vectorStoreId && { vector_store_id: vectorStoreId }),
|
||||
...(providerSpecificParams && providerSpecificParams),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -22,17 +22,51 @@ vi.mock("../vector_store_providers", () => ({
|
|||
BEDROCK: "Amazon Bedrock",
|
||||
OPENAI: "OpenAI",
|
||||
AZURE_OPENAI: "Azure OpenAI",
|
||||
S3Vectors: "AWS S3 Vectors",
|
||||
},
|
||||
vectorStoreProviderMap: {
|
||||
BEDROCK: "bedrock",
|
||||
OPENAI: "openai",
|
||||
AZURE_OPENAI: "azure_openai",
|
||||
S3Vectors: "s3_vectors",
|
||||
},
|
||||
vectorStoreProviderLogoMap: {
|
||||
"Amazon Bedrock": "https://example.com/bedrock.png",
|
||||
"OpenAI": "https://example.com/openai.png",
|
||||
"Azure OpenAI": "https://example.com/azure.png",
|
||||
"AWS S3 Vectors": "https://example.com/aws.png",
|
||||
},
|
||||
getProviderSpecificFields: vi.fn((provider: string) => {
|
||||
if (provider === "s3_vectors") {
|
||||
return [
|
||||
{
|
||||
name: "vector_bucket_name",
|
||||
label: "Vector Bucket Name",
|
||||
tooltip: "S3 bucket name for vector storage",
|
||||
placeholder: "my-vector-bucket",
|
||||
required: true,
|
||||
type: "text",
|
||||
},
|
||||
{
|
||||
name: "aws_region_name",
|
||||
label: "AWS Region",
|
||||
tooltip: "AWS region",
|
||||
placeholder: "us-west-2",
|
||||
required: true,
|
||||
type: "text",
|
||||
},
|
||||
{
|
||||
name: "embedding_model",
|
||||
label: "Embedding Model",
|
||||
tooltip: "Embedding model to use",
|
||||
placeholder: "text-embedding-3-small",
|
||||
required: true,
|
||||
type: "select",
|
||||
},
|
||||
];
|
||||
}
|
||||
return [];
|
||||
}),
|
||||
}));
|
||||
|
||||
describe("CreateVectorStore", () => {
|
||||
|
|
@ -43,9 +77,9 @@ describe("CreateVectorStore", () => {
|
|||
it("should render the component successfully", () => {
|
||||
render(<CreateVectorStore accessToken="test-token" />);
|
||||
|
||||
expect(screen.getByText("Create Vector Store")).toBeInTheDocument();
|
||||
expect(screen.getAllByText("Create Vector Store").length).toBeGreaterThan(0);
|
||||
expect(screen.getByText("Step 1: Upload Documents")).toBeInTheDocument();
|
||||
expect(screen.getByText("Step 2: Select Provider")).toBeInTheDocument();
|
||||
expect(screen.getByText("Step 2: Configure Vector Store")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should display upload area with correct text", () => {
|
||||
|
|
@ -123,7 +157,15 @@ describe("CreateVectorStore", () => {
|
|||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mockRagIngestCall).toHaveBeenCalledWith("test-token", expect.any(File), "bedrock", undefined);
|
||||
expect(mockRagIngestCall).toHaveBeenCalledWith(
|
||||
"test-token",
|
||||
expect.any(File),
|
||||
"bedrock",
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -163,4 +205,72 @@ describe("CreateVectorStore", () => {
|
|||
expect(screen.getByText("Vector Store Created Successfully")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it("should display S3 Vectors provider-specific fields when selected", async () => {
|
||||
render(<CreateVectorStore accessToken="test-token" />);
|
||||
|
||||
// Find and click the provider dropdown
|
||||
const providerSelect = screen.getByRole("combobox");
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.mouseDown(providerSelect);
|
||||
});
|
||||
|
||||
// Wait for dropdown options to appear
|
||||
await waitFor(() => {
|
||||
const s3Option = screen.queryByText("AWS S3 Vectors");
|
||||
if (s3Option) {
|
||||
fireEvent.click(s3Option);
|
||||
}
|
||||
});
|
||||
|
||||
// Check if S3-specific fields are displayed
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByText("Vector Bucket Name")).toBeInTheDocument();
|
||||
expect(screen.queryByText("AWS Region")).toBeInTheDocument();
|
||||
expect(screen.queryByText("Embedding Model")).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
it("should validate S3 Vectors required fields before submission", async () => {
|
||||
render(<CreateVectorStore accessToken="test-token" />);
|
||||
|
||||
// Upload a file first
|
||||
const file = new File(["test content"], "test.pdf", { type: "application/pdf" });
|
||||
const uploadInput = document.querySelector('input[type="file"]') as HTMLInputElement;
|
||||
|
||||
await act(async () => {
|
||||
if (uploadInput) {
|
||||
fireEvent.change(uploadInput, { target: { files: [file] } });
|
||||
}
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText("Uploaded Documents (1)")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
// Select S3 Vectors provider
|
||||
const providerSelect = screen.getByRole("combobox");
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.mouseDown(providerSelect);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
const s3Option = screen.queryByText("AWS S3 Vectors");
|
||||
if (s3Option) {
|
||||
fireEvent.click(s3Option);
|
||||
}
|
||||
});
|
||||
|
||||
// Try to create without filling required fields
|
||||
const createButton = screen.getByRole("button", { name: /Create Vector Store/i });
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.click(createButton);
|
||||
});
|
||||
|
||||
// Should show validation warning (mocked message.warning would be called)
|
||||
// The actual validation happens in the component
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,8 +10,11 @@ import {
|
|||
VectorStoreProviders,
|
||||
vectorStoreProviderLogoMap,
|
||||
vectorStoreProviderMap,
|
||||
getProviderSpecificFields,
|
||||
VectorStoreFieldConfig,
|
||||
} from "../vector_store_providers";
|
||||
import NotificationsManager from "../molecules/notifications_manager";
|
||||
import S3VectorsConfig from "./S3VectorsConfig";
|
||||
|
||||
const { Dragger } = Upload;
|
||||
|
||||
|
|
@ -28,6 +31,7 @@ const CreateVectorStore: React.FC<CreateVectorStoreProps> = ({ accessToken, onSu
|
|||
const [vectorStoreName, setVectorStoreName] = useState<string>("");
|
||||
const [vectorStoreDescription, setVectorStoreDescription] = useState<string>("");
|
||||
const [ingestResults, setIngestResults] = useState<RAGIngestResponse[]>([]);
|
||||
const [providerParams, setProviderParams] = useState<Record<string, any>>({});
|
||||
|
||||
const uploadProps: UploadProps = {
|
||||
name: "file",
|
||||
|
|
@ -92,6 +96,15 @@ const CreateVectorStore: React.FC<CreateVectorStoreProps> = ({ accessToken, onSu
|
|||
return;
|
||||
}
|
||||
|
||||
// Validate provider-specific required fields
|
||||
const requiredFields = getProviderSpecificFields(selectedProvider).filter((field) => field.required);
|
||||
for (const field of requiredFields) {
|
||||
if (!providerParams[field.name]) {
|
||||
message.warning(`Please provide ${field.label}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!accessToken) {
|
||||
message.error("No access token available");
|
||||
return;
|
||||
|
|
@ -118,7 +131,8 @@ const CreateVectorStore: React.FC<CreateVectorStoreProps> = ({ accessToken, onSu
|
|||
selectedProvider,
|
||||
vectorStoreId, // Use the same vector store ID for subsequent uploads
|
||||
vectorStoreName || undefined,
|
||||
vectorStoreDescription || undefined
|
||||
vectorStoreDescription || undefined,
|
||||
providerParams
|
||||
);
|
||||
|
||||
// Store the vector store ID from the first successful ingest
|
||||
|
|
@ -298,6 +312,74 @@ const CreateVectorStore: React.FC<CreateVectorStoreProps> = ({ accessToken, onSu
|
|||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
{/* S3 Vectors Configuration */}
|
||||
{selectedProvider === "s3_vectors" && (
|
||||
<S3VectorsConfig
|
||||
accessToken={accessToken}
|
||||
providerParams={providerParams}
|
||||
onParamsChange={setProviderParams}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Other Provider-specific fields */}
|
||||
{selectedProvider !== "s3_vectors" &&
|
||||
getProviderSpecificFields(selectedProvider).map((field: VectorStoreFieldConfig) => {
|
||||
if (field.type === "select") {
|
||||
// For embedding model selection, we'd need to fetch available models
|
||||
// For now, provide a text input as fallback
|
||||
return (
|
||||
<Form.Item
|
||||
key={field.name}
|
||||
label={
|
||||
<span>
|
||||
{field.label}{" "}
|
||||
<Tooltip title={field.tooltip}>
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
required={field.required}
|
||||
>
|
||||
<Input
|
||||
value={providerParams[field.name] || ""}
|
||||
onChange={(e) =>
|
||||
setProviderParams((prev) => ({ ...prev, [field.name]: e.target.value }))
|
||||
}
|
||||
placeholder={field.placeholder}
|
||||
size="large"
|
||||
className="rounded-md"
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Form.Item
|
||||
key={field.name}
|
||||
label={
|
||||
<span>
|
||||
{field.label}{" "}
|
||||
<Tooltip title={field.tooltip}>
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
required={field.required}
|
||||
>
|
||||
<Input
|
||||
type={field.type === "password" ? "password" : "text"}
|
||||
value={providerParams[field.name] || ""}
|
||||
onChange={(e) =>
|
||||
setProviderParams((prev) => ({ ...prev, [field.name]: e.target.value }))
|
||||
}
|
||||
placeholder={field.placeholder}
|
||||
size="large"
|
||||
className="rounded-md"
|
||||
/>
|
||||
</Form.Item>
|
||||
);
|
||||
})}
|
||||
</Form>
|
||||
|
||||
<div className="flex justify-end">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,203 @@
|
|||
import { render, screen, fireEvent, waitFor, act } from "@testing-library/react";
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import S3VectorsConfig from "./S3VectorsConfig";
|
||||
import * as fetchModels from "../playground/llm_calls/fetch_models";
|
||||
|
||||
// Mock fetchAvailableModels
|
||||
vi.mock("../playground/llm_calls/fetch_models", () => ({
|
||||
fetchAvailableModels: vi.fn(),
|
||||
}));
|
||||
|
||||
describe("S3VectorsConfig", () => {
|
||||
const mockOnParamsChange = vi.fn();
|
||||
const defaultProps = {
|
||||
accessToken: "test-token",
|
||||
providerParams: {},
|
||||
onParamsChange: mockOnParamsChange,
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("should render the component successfully", () => {
|
||||
vi.spyOn(fetchModels, "fetchAvailableModels").mockResolvedValue([]);
|
||||
|
||||
render(<S3VectorsConfig {...defaultProps} />);
|
||||
|
||||
expect(screen.getByText("AWS S3 Vectors Setup")).toBeInTheDocument();
|
||||
expect(screen.getByText("Vector Bucket Name")).toBeInTheDocument();
|
||||
expect(screen.getByText("Index Name")).toBeInTheDocument();
|
||||
expect(screen.getByText("AWS Region")).toBeInTheDocument();
|
||||
expect(screen.getByText("Embedding Model")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should display setup instructions", () => {
|
||||
vi.spyOn(fetchModels, "fetchAvailableModels").mockResolvedValue([]);
|
||||
|
||||
render(<S3VectorsConfig {...defaultProps} />);
|
||||
|
||||
expect(
|
||||
screen.getByText(/AWS S3 Vectors allows you to store and query vector embeddings directly in S3/)
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByText(/Vector buckets and indexes will be automatically created/)).toBeInTheDocument();
|
||||
expect(screen.getByText(/Vector dimensions are auto-detected/)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should fetch embedding models on mount", async () => {
|
||||
const mockModels = [
|
||||
{ model_group: "text-embedding-3-small", mode: "embedding" },
|
||||
{ model_group: "text-embedding-3-large", mode: "embedding" },
|
||||
{ model_group: "gpt-4", mode: "chat" },
|
||||
];
|
||||
|
||||
const fetchSpy = vi.spyOn(fetchModels, "fetchAvailableModels").mockResolvedValue(mockModels);
|
||||
|
||||
render(<S3VectorsConfig {...defaultProps} />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchSpy).toHaveBeenCalledWith("test-token");
|
||||
});
|
||||
});
|
||||
|
||||
it("should filter and display only embedding models", async () => {
|
||||
const mockModels = [
|
||||
{ model_group: "text-embedding-3-small", mode: "embedding" },
|
||||
{ model_group: "text-embedding-3-large", mode: "embedding" },
|
||||
{ model_group: "gpt-4", mode: "chat" },
|
||||
{ model_group: "gpt-3.5-turbo", mode: "chat" },
|
||||
];
|
||||
|
||||
vi.spyOn(fetchModels, "fetchAvailableModels").mockResolvedValue(mockModels);
|
||||
|
||||
render(<S3VectorsConfig {...defaultProps} />);
|
||||
|
||||
// Wait for models to load
|
||||
await waitFor(() => {
|
||||
expect(fetchModels.fetchAvailableModels).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
// The component should filter to only embedding models internally
|
||||
// We can verify this by checking the component loaded successfully
|
||||
expect(screen.getByText("Embedding Model")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should call onParamsChange when vector bucket name changes", async () => {
|
||||
vi.spyOn(fetchModels, "fetchAvailableModels").mockResolvedValue([]);
|
||||
|
||||
render(<S3VectorsConfig {...defaultProps} />);
|
||||
|
||||
const bucketInput = screen.getByPlaceholderText("my-vector-bucket");
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.change(bucketInput, { target: { value: "test-bucket" } });
|
||||
});
|
||||
|
||||
expect(mockOnParamsChange).toHaveBeenCalledWith({
|
||||
vector_bucket_name: "test-bucket",
|
||||
});
|
||||
});
|
||||
|
||||
it("should call onParamsChange when AWS region changes", async () => {
|
||||
vi.spyOn(fetchModels, "fetchAvailableModels").mockResolvedValue([]);
|
||||
|
||||
render(<S3VectorsConfig {...defaultProps} />);
|
||||
|
||||
const regionInput = screen.getByPlaceholderText("us-west-2");
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.change(regionInput, { target: { value: "us-east-1" } });
|
||||
});
|
||||
|
||||
expect(mockOnParamsChange).toHaveBeenCalledWith({
|
||||
aws_region_name: "us-east-1",
|
||||
});
|
||||
});
|
||||
|
||||
it("should call onParamsChange when embedding model is selected", async () => {
|
||||
const mockModels = [
|
||||
{ model_group: "text-embedding-3-small", mode: "embedding" },
|
||||
{ model_group: "text-embedding-3-large", mode: "embedding" },
|
||||
];
|
||||
|
||||
vi.spyOn(fetchModels, "fetchAvailableModels").mockResolvedValue(mockModels);
|
||||
|
||||
render(<S3VectorsConfig {...defaultProps} />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchModels.fetchAvailableModels).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
// Find the Select component and trigger change directly
|
||||
const selectElement = screen.getByRole("combobox");
|
||||
|
||||
await act(async () => {
|
||||
// Simulate selecting a value by firing the change event
|
||||
fireEvent.change(selectElement, { target: { value: "text-embedding-3-small" } });
|
||||
});
|
||||
|
||||
// The component should handle the selection
|
||||
expect(screen.getByText("Embedding Model")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should preserve existing params when updating a field", async () => {
|
||||
vi.spyOn(fetchModels, "fetchAvailableModels").mockResolvedValue([]);
|
||||
|
||||
const existingParams = {
|
||||
vector_bucket_name: "existing-bucket",
|
||||
aws_region_name: "us-west-2",
|
||||
};
|
||||
|
||||
render(<S3VectorsConfig {...defaultProps} providerParams={existingParams} />);
|
||||
|
||||
const indexInput = screen.getByPlaceholderText("my-vector-index");
|
||||
|
||||
await act(async () => {
|
||||
fireEvent.change(indexInput, { target: { value: "my-index" } });
|
||||
});
|
||||
|
||||
expect(mockOnParamsChange).toHaveBeenCalledWith({
|
||||
vector_bucket_name: "existing-bucket",
|
||||
aws_region_name: "us-west-2",
|
||||
index_name: "my-index",
|
||||
});
|
||||
});
|
||||
|
||||
it("should display existing param values", () => {
|
||||
vi.spyOn(fetchModels, "fetchAvailableModels").mockResolvedValue([]);
|
||||
|
||||
const existingParams = {
|
||||
vector_bucket_name: "my-bucket",
|
||||
index_name: "my-index",
|
||||
aws_region_name: "eu-west-1",
|
||||
embedding_model: "text-embedding-3-small",
|
||||
};
|
||||
|
||||
render(<S3VectorsConfig {...defaultProps} providerParams={existingParams} />);
|
||||
|
||||
expect(screen.getByDisplayValue("my-bucket")).toBeInTheDocument();
|
||||
expect(screen.getByDisplayValue("my-index")).toBeInTheDocument();
|
||||
expect(screen.getByDisplayValue("eu-west-1")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("should handle model fetch error gracefully", async () => {
|
||||
const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
||||
vi.spyOn(fetchModels, "fetchAvailableModels").mockRejectedValue(new Error("Failed to fetch models"));
|
||||
|
||||
render(<S3VectorsConfig {...defaultProps} />);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(consoleErrorSpy).toHaveBeenCalledWith("Error fetching embedding models:", expect.any(Error));
|
||||
});
|
||||
|
||||
consoleErrorSpy.mockRestore();
|
||||
});
|
||||
|
||||
it("should not fetch models if accessToken is null", () => {
|
||||
const fetchSpy = vi.spyOn(fetchModels, "fetchAvailableModels");
|
||||
|
||||
render(<S3VectorsConfig {...defaultProps} accessToken={null} />);
|
||||
|
||||
expect(fetchSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { Alert, Form, Input, Select, Tooltip } from "antd";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { fetchAvailableModels, ModelGroup } from "../playground/llm_calls/fetch_models";
|
||||
|
||||
interface S3VectorsConfigProps {
|
||||
accessToken: string | null;
|
||||
providerParams: Record<string, any>;
|
||||
onParamsChange: (params: Record<string, any>) => void;
|
||||
}
|
||||
|
||||
const S3VectorsConfig: React.FC<S3VectorsConfigProps> = ({
|
||||
accessToken,
|
||||
providerParams,
|
||||
onParamsChange,
|
||||
}) => {
|
||||
const [embeddingModels, setEmbeddingModels] = useState<ModelGroup[]>([]);
|
||||
const [isLoadingModels, setIsLoadingModels] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!accessToken) return;
|
||||
|
||||
const loadModels = async () => {
|
||||
setIsLoadingModels(true);
|
||||
try {
|
||||
const models = await fetchAvailableModels(accessToken);
|
||||
// Filter for embedding models only
|
||||
const embeddingOnly = models.filter((model) => model.mode === "embedding");
|
||||
setEmbeddingModels(embeddingOnly);
|
||||
} catch (error) {
|
||||
console.error("Error fetching embedding models:", error);
|
||||
} finally {
|
||||
setIsLoadingModels(false);
|
||||
}
|
||||
};
|
||||
|
||||
loadModels();
|
||||
}, [accessToken]);
|
||||
|
||||
const handleFieldChange = (fieldName: string, value: string) => {
|
||||
onParamsChange({
|
||||
...providerParams,
|
||||
[fieldName]: value,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* S3 Vectors Setup Instructions */}
|
||||
<Alert
|
||||
message="AWS S3 Vectors Setup"
|
||||
description={
|
||||
<div>
|
||||
<p>AWS S3 Vectors allows you to store and query vector embeddings directly in S3:</p>
|
||||
<ul style={{ marginLeft: "16px", marginTop: "8px" }}>
|
||||
<li>Vector buckets and indexes will be automatically created if they don't exist</li>
|
||||
<li>Vector dimensions are auto-detected from your selected embedding model</li>
|
||||
<li>Ensure your AWS credentials have permissions for S3 Vectors operations</li>
|
||||
<li>
|
||||
Learn more:{" "}
|
||||
<a
|
||||
href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-vector-buckets.html"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
AWS S3 Vectors Documentation
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
type="info"
|
||||
showIcon
|
||||
style={{ marginBottom: "16px" }}
|
||||
/>
|
||||
|
||||
{/* Vector Bucket Name */}
|
||||
<Form.Item
|
||||
label={
|
||||
<span>
|
||||
Vector Bucket Name{" "}
|
||||
<Tooltip title="S3 bucket name for vector storage (will be auto-created if it doesn't exist)">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
required
|
||||
>
|
||||
<Input
|
||||
value={providerParams.vector_bucket_name || ""}
|
||||
onChange={(e) => handleFieldChange("vector_bucket_name", e.target.value)}
|
||||
placeholder="my-vector-bucket"
|
||||
size="large"
|
||||
className="rounded-md"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
{/* Index Name (Optional) */}
|
||||
<Form.Item
|
||||
label={
|
||||
<span>
|
||||
Index Name{" "}
|
||||
<Tooltip title="Name for the vector index (optional, will be auto-generated if not provided)">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<Input
|
||||
value={providerParams.index_name || ""}
|
||||
onChange={(e) => handleFieldChange("index_name", e.target.value)}
|
||||
placeholder="my-vector-index"
|
||||
size="large"
|
||||
className="rounded-md"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
{/* AWS Region */}
|
||||
<Form.Item
|
||||
label={
|
||||
<span>
|
||||
AWS Region{" "}
|
||||
<Tooltip title="AWS region where the S3 bucket is located (e.g., us-west-2)">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
required
|
||||
>
|
||||
<Input
|
||||
value={providerParams.aws_region_name || ""}
|
||||
onChange={(e) => handleFieldChange("aws_region_name", e.target.value)}
|
||||
placeholder="us-west-2"
|
||||
size="large"
|
||||
className="rounded-md"
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
{/* Embedding Model */}
|
||||
<Form.Item
|
||||
label={
|
||||
<span>
|
||||
Embedding Model{" "}
|
||||
<Tooltip title="Select the embedding model to use for vector generation">
|
||||
<InfoCircleOutlined style={{ marginLeft: "4px" }} />
|
||||
</Tooltip>
|
||||
</span>
|
||||
}
|
||||
required
|
||||
>
|
||||
<Select
|
||||
value={providerParams.embedding_model || undefined}
|
||||
onChange={(value) => handleFieldChange("embedding_model", value)}
|
||||
placeholder="Select an embedding model"
|
||||
size="large"
|
||||
showSearch
|
||||
loading={isLoadingModels}
|
||||
filterOption={(input, option) =>
|
||||
(option?.label ?? "").toLowerCase().includes(input.toLowerCase())
|
||||
}
|
||||
options={embeddingModels.map((model) => ({
|
||||
value: model.model_group,
|
||||
label: model.model_group,
|
||||
}))}
|
||||
style={{ width: "100%" }}
|
||||
/>
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default S3VectorsConfig;
|
||||
|
|
@ -5,6 +5,7 @@ export enum VectorStoreProviders {
|
|||
OpenAI = "OpenAI",
|
||||
Azure = "Azure OpenAI",
|
||||
Milvus = "Milvus",
|
||||
S3Vectors = "AWS S3 Vectors",
|
||||
}
|
||||
|
||||
export const vectorStoreProviderMap: Record<string, string> = {
|
||||
|
|
@ -14,6 +15,7 @@ export const vectorStoreProviderMap: Record<string, string> = {
|
|||
OpenAI: "openai",
|
||||
Azure: "azure",
|
||||
Milvus: "milvus",
|
||||
S3Vectors: "s3_vectors",
|
||||
};
|
||||
|
||||
const asset_logos_folder = "../ui/assets/logos/";
|
||||
|
|
@ -25,6 +27,7 @@ export const vectorStoreProviderLogoMap: Record<string, string> = {
|
|||
[VectorStoreProviders.OpenAI]: `${asset_logos_folder}openai_small.svg`,
|
||||
[VectorStoreProviders.Azure]: `${asset_logos_folder}microsoft_azure.svg`,
|
||||
[VectorStoreProviders.Milvus]: `${asset_logos_folder}milvus.svg`,
|
||||
[VectorStoreProviders.S3Vectors]: `${asset_logos_folder}aws.svg`,
|
||||
};
|
||||
|
||||
// Define field types for provider-specific configurations
|
||||
|
|
@ -114,6 +117,40 @@ export const vectorStoreProviderFields: Record<string, VectorStoreFieldConfig[]>
|
|||
type: "select",
|
||||
},
|
||||
],
|
||||
s3_vectors: [
|
||||
{
|
||||
name: "vector_bucket_name",
|
||||
label: "Vector Bucket Name",
|
||||
tooltip: "S3 bucket name for vector storage (will be auto-created if it doesn't exist)",
|
||||
placeholder: "my-vector-bucket",
|
||||
required: true,
|
||||
type: "text",
|
||||
},
|
||||
{
|
||||
name: "index_name",
|
||||
label: "Index Name",
|
||||
tooltip: "Name for the vector index (optional, will be auto-generated if not provided)",
|
||||
placeholder: "my-vector-index",
|
||||
required: false,
|
||||
type: "text",
|
||||
},
|
||||
{
|
||||
name: "aws_region_name",
|
||||
label: "AWS Region",
|
||||
tooltip: "AWS region where the S3 bucket is located (e.g., us-west-2)",
|
||||
placeholder: "us-west-2",
|
||||
required: true,
|
||||
type: "text",
|
||||
},
|
||||
{
|
||||
name: "embedding_model",
|
||||
label: "Embedding Model",
|
||||
tooltip: "Select the embedding model to use for vector generation",
|
||||
placeholder: "text-embedding-3-small",
|
||||
required: true,
|
||||
type: "select",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const getVectorStoreProviderLogoAndName = (providerValue: string): { logo: string; displayName: string } => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue