API Spring AI — Semantic Search (OpenAI v1)

A small Spring Boot demo that shows how to use Spring AI with OpenAI to:

View source on GitHub Portfolio index

A small Spring Boot demo that shows how to use Spring AI with OpenAI to:

It is part of a training series on Java + Spring AI (03 - Semantic Search).

What this project demonstrates

1. Embeddings & cosine similarity (SemanticSearchRunner)

SemanticSearchRunner is a CommandLineRunner bean that runs automatically on application startup. It uses Spring AI's EmbeddingModel to turn text into vectors and then measures similarity between them with a hand-written cosine similarity function.

The active example (embedding4) runs a tiny semantic search:

  1. Takes a query string (e.g. "Pinsa", a misspelling of "Pizza").
  2. Embeds a list of candidate documents (Vehículo, Coche, Carro, Bicicleta, Avión, Pizza).
  3. Embeds the query and compares it against every document using cosine similarity.
  4. Prints the documents ranked by similarity score, highest first.

This shows the core idea behind semantic search: instead of exact keyword matching, texts are compared by the meaning captured in their embedding vectors, so even a misspelled or related query can surface the right result.

The class also keeps several other example runners (currently disabled via commented-out @Bean) that were used to explore the same concept step by step:

You can enable any of these by uncommenting the corresponding @Bean annotation.

2. Chat endpoint (ChatController / ChatService)

A minimal REST API wraps Spring AI's ChatClient to send a free-form question to the OpenAI chat model and return its answer:

Tech stack

Project structure

src/main/java/.../com/mx/development/jose/said/
├── ApiSpringAiDemoV1Application.java   # Spring Boot entry point
├── controller/
│   └── ChatController.java             # REST endpoint for chat
├── dto/
│   └── Resultado.java                  # (text, score) pair used in similarity results
├── runner/
│   └── SemanticSearchRunner.java       # Embedding & cosine similarity examples
└── service/
    ├── ChatService.java                # Chat service contract
    └── ChatServiceImpl.java            # Chat service implementation using ChatClient

src/main/resources/
├── application.yml                     # Base config (port, active profile, logging)
└── application-openai.yml              # OpenAI API key configuration (profile: openai)

Configuration

The application runs with the openai Spring profile active by default (see application.yml). The OpenAI API key is read from an environment variable:

# application-openai.yml
spring:
  ai:
    openai:
      api-key: ${API_KEY}

You need a valid OpenAI API key — see https://platform.openai.com/api-keys.

The server runs on port 8088 by default (server.port in application.yml).

Running the project

  1. Export your OpenAI API key:

bash export API_KEY=sk-...

  1. Run the application with the Maven Wrapper:

bash ./mvnw spring-boot:run

On startup, SemanticSearchRunner will print the embedding/similarity results to the console.

  1. Call the chat endpoint:

bash curl "http://localhost:8088/api/v1/chat-service/chat?question=What%20is%20Spring%20AI%3F"

Notes