オンラインでショッピングをしていて、名前がわからないお気に入りの商品に出会ったと想像してください。写真をアップロードして、アプリがそれを見つけてくれたら素晴らしいと思いませんか?
この記事では、Spring Boot と Google Cloud Vertex AI を使用した画像ベースの商品検索機能を構築する方法を説明します。
この機能を使用すると、ユーザーは画像をアップロードし、それに一致する商品のリストを受け取ることができるため、検索エクスペリエンスがより直感的で視覚的なものになります。
画像ベースの商品検索機能は、Google Cloud Vertex AI を利用して画像を処理し、関連するキーワードを抽出します。これらのキーワードは、データベース内で一致する製品を検索するために使用されます。
この機能を設定するプロセスを段階的に説明します。
まず、このために Google コンソールで新しいプロジェクトを作成する必要があります。
すでにアカウントをお持ちの場合は、https://console.cloud.google.com にアクセスして新しいアカウントを作成する必要があります。アカウントをお持ちの場合は、アカウントにサインインします。
銀行口座を追加すると、Google Cloud の無料トライアルが提供されます。
アカウントを作成するか、既存のアカウントにサインインしたら、新しいプロジェクトを作成できます。
検索バーで Vertex AI を見つけ、推奨される API をすべて有効にする必要があります。
Vertex AI は、ML モデルの開発、デプロイ、管理を簡素化するように設計された Google Cloud のフルマネージド機械学習 (ML) プラットフォームです。 AutoML、カスタム モデル トレーニング、ハイパーパラメーター調整、モデル モニタリングなどのツールとサービスを提供することで、ML モデルを大規模に構築、トレーニング、デプロイできます
Gemini 1.5 Flash は、Google の Gemini モデル ファミリの一部であり、特に ML アプリケーションでの効率的で高性能な推論のために設計されています。 Gemini モデルは、Google によって開発された一連の高度な AI モデルであり、自然言語処理 (NLP)、ビジョン タスク、その他の AI を利用したアプリケーションでよく使用されます
注: 他のフレームワークの場合は、https://aistudio.google.com/app/prompts/new_chat で Gemini API を直接使用できます。構造プロンプト機能を使用すると、入力と一致するように出力をカスタマイズできるため、より良い結果が得られます。
このステップでは、アプリケーションに合わせてプロンプトをカスタマイズする必要があります。
Vertex AI Studio は、プロンプト ギャラリー で多くのサンプル プロンプトを提供しています。サンプル 画像テキストを JSON に変換して、商品画像に関連するキーワードを抽出します。
私のアプリケーションは CarShop なので、次のようなプロンプトを作成します。モデルが画像に関連するキーワードのリストを返してくれることを期待しています。
私のプロンプト: 名前の車をリストのキーワードに抽出し、JSON で出力します。車に関する情報が見つからない場合は、空のリストを出力してください。n応答例: ["rolls"、"royce"、"wraith"]
アプリケーションに合わせて適切なプロンプトをカスタマイズした後。次に、Spring Boot アプリケーションと統合する方法を検討します。
私は自動車に関する電子商取引アプリケーションを構築しました。そこで、画像から車を探したいと思います。
まず、pom.xml ファイルで依存関係を更新する必要があります。
<!-- config version for dependency--> <properties> <spring-cloud-gcp.version>5.1.2</spring-cloud-gcp.version> <google-cloud-bom.version>26.32.0</google-cloud-bom.version> </properties> <!-- In your dependencyManagement, please add 2 dependencies below --> <dependencyManagement> <dependencies> <dependency> <groupId>com.google.cloud</groupId> <artifactId>spring-cloud-gcp-dependencies</artifactId> <version>${spring-cloud-gcp.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.google.cloud</groupId> <artifactId>libraries-bom</artifactId> <version>${google-cloud-bom.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <!-- In your tab dependencies, please add the dependency below --> <dependencies> <dependency> <groupId>com.google.cloud</groupId> <artifactId>google-cloud-vertexai</artifactId> </dependency> </dependencies>
pom.xml ファイルで構成を行った後、構成クラス GeminiConfig.java
を作成します。
import com.google.cloud.vertexai.VertexAI; import com.google.cloud.vertexai.generativeai.GenerativeModel; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) public class GeminiConfig { private static final String MODEL_NAME = "gemini-1.5-flash"; private static final String LOCATION = "asia-southeast1"; private static final String PROJECT_ID = "yasmini"; @Bean public VertexAI vertexAI() { return new VertexAI(PROJECT_ID, LOCATION); } @Bean public GenerativeModel getModel(VertexAI vertexAI) { return new GenerativeModel(MODEL_NAME, vertexAI); } }
2 番目に、車の検索機能を実装するためのレイヤー Service、Controller を作成します。クラスサービスを作成します。
Gemini API はマークダウン形式で応答するため、JSON への変換を支援する関数を作成する必要があります。JSON から Java のリスト文字列に変換します。
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.cloud.vertexai.api.Content; import com.google.cloud.vertexai.api.GenerateContentResponse; import com.google.cloud.vertexai.api.Part; import com.google.cloud.vertexai.generativeai.*; import com.learning.yasminishop.common.entity.Product; import com.learning.yasminishop.common.exception.AppException; import com.learning.yasminishop.common.exception.ErrorCode; import com.learning.yasminishop.product.ProductRepository; import com.learning.yasminishop.product.dto.response.ProductResponse; import com.learning.yasminishop.product.mapper.ProductMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; @Service @RequiredArgsConstructor @Slf4j @Transactional(readOnly = true) public class YasMiniAIService { private final GenerativeModel generativeModel; private final ProductRepository productRepository; private final ProductMapper productMapper; public List<ProductResponse> findCarByImage(MultipartFile file){ try { var prompt = "Extract the name car to a list keyword and output them in JSON. If you don't find any information about the car, please output the list empty.\nExample response: [\"rolls\", \"royce\", \"wraith\"]"; var content = this.generativeModel.generateContent( ContentMaker.fromMultiModalData( PartMaker.fromMimeTypeAndData(Objects.requireNonNull(file.getContentType()), file.getBytes()), prompt ) ); String jsonContent = ResponseHandler.getText(content); log.info("Extracted keywords from image: {}", jsonContent); List<String> keywords = convertJsonToList(jsonContent).stream() .map(String::toLowerCase) .toList(); Set<Product> results = new HashSet<>(); for (String keyword : keywords) { List<Product> products = productRepository.searchByKeyword(keyword); results.addAll(products); } return results.stream() .map(productMapper::toProductResponse) .toList(); } catch (Exception e) { log.error("Error finding car by image", e); return List.of(); } } private List<String> convertJsonToList(String markdown) throws JsonProcessingException { ObjectMapper objectMapper = new ObjectMapper(); String parseJson = markdown; if(markdown.contains("``` json")){ parseJson = extractJsonFromMarkdown(markdown); } return objectMapper.readValue(parseJson, List.class); } private String extractJsonFromMarkdown(String markdown) { return markdown.replace(" ```json\n", "").replace("\n``` ", ""); } }
フロントエンドのエンドポイントを作成するにはコントローラー クラスを作成する必要があります
import com.learning.yasminishop.product.dto.response.ProductResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.util.List; @RestController @RequestMapping("/ai") @RequiredArgsConstructor @Slf4j public class YasMiniAIController { private final YasMiniAIService yasMiniAIService; @PostMapping public List<ProductResponse> findCar(@RequestParam("file") MultipartFile file) { var response = yasMiniAIService.findCarByImage(file); return response; } }
Spring Boot アプリケーションはユーザーの身元を確認できず、Google Cloud のリソースを受け入れることができません。
そのため、Google にログインして認証を行う必要があります。
リンクチュートリアル: https://cloud.google.com/sdk/docs/install
上記のリンクを確認して、マシンにインストールしてください
gcloud auth login
注: ログインすると、認証情報が Google Maven パッケージに保存されるため、Spring Boot アプリケーションを再起動するときに再度ログインする必要はありません。
これらは私のプロジェクト E-commerce に基づいて実装されているため、プロジェクトとフレームワークとのマッチングを変更できます。 Spring Boot (NestJs など) 以外の他のフレームワークでは、https://aistudio.google.com/app/prompts/new_chat を使用できます。新しい Google Cloud アカウントを作成する必要はありません。
詳細な実装は私のリポジトリで確認できます:
バックエンド: https://github.com/duongminhhieu/YasMiniShop
フロントエンド: https://github.com/duongminhhieu/YasMini-Frontend
楽しく学んでください!!!
以上がSpring Boot、Google Cloud Vertex AI、Gemini モデルを使用した画像ベースの商品検索の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。