https://github.com/aborroy/spring-ai-summarizer
Tutorial to create a summarizer endpoint with Spring AI and Docker Model Runner
https://github.com/aborroy/spring-ai-summarizer
Last synced: 4 months ago
JSON representation
Tutorial to create a summarizer endpoint with Spring AI and Docker Model Runner
- Host: GitHub
- URL: https://github.com/aborroy/spring-ai-summarizer
- Owner: aborroy
- License: apache-2.0
- Created: 2025-06-05T09:57:43.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-06-05T11:43:37.000Z (about 1 year ago)
- Last Synced: 2025-06-05T12:30:45.530Z (about 1 year ago)
- Size: 14.6 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Lab: Building a Local PDF Summarizer with Spring Boot & Docker-Hosted LLM
Welcome to this hands-on lab! You'll create a **Spring Boot 3.5** microservice that transforms any PDF into a concise summary using a **local Large Language Model** (LLM) served through Docker Model Runner. By the end, you'll have a running REST endpoint (`POST /api/summarize`) that accepts a PDF and returns a summary – **without ever sending data to the cloud**.
## Learning Objectives
1. Scaffold a modern Spring Boot project with proper dependency management
2. Configure Spring AI to communicate with a locally running LLM (Mistral) via Docker Model Runner
3. Implement PDF processing with page-by-page text extraction using Spring AI utilities
4. Build a multi-stage summarization pipeline with prompt chaining
5. Expose functionality through a robust REST API with proper error handling
6. Package the complete solution with Docker Compose for easy deployment
## Prerequisites & Environment Setup
| Tool | Minimum Version | Check Command | Installation Notes |
| -------------- | --------------- | -------------------- | ------------------ |
| Java (Temurin) | 21 | `java --version` | Use SDKMAN or official installer |
| Maven | 3.9 | `mvn --version` | Bundled with most IDEs |
| Docker Desktop | 4.40 | `docker --version` | Required for Model Runner |
| IDE | Latest | N/A | IntelliJ IDEA recommended |
**Verification Task:** Run all check commands. If any fail, install the missing tools before proceeding.
## Step 0: Download and Verify LLM Model
We'll use **Mistral 7B** - it's lightweight (~4GB) yet powerful enough for quality summarization.
**Your Task:**
1. Use `docker model pull` to download the `ai/mistral` model
2. Verify the download with `docker model list`
3. Check if Docker Model Runner is active with `docker model status`
**Common Issues:**
- Command not recognized? Your Docker Desktop version is too old
- Download hanging? Check your internet connection and Docker daemon
**Success Indicator:** You should see "Docker Model Running" and the mistral model listed.
## Step 1: Create Project Structure
**Your Task:**
1. Choose meaningful names:
- Group ID: Use your domain (e.g., `com.yourname.pdfsummarizer`)
- Artifact ID: Something descriptive (e.g., `pdf-summarizer-service`)
2. Generate a Maven project using the `maven-archetype-quickstart` archetype
```bash
mvn archetype:generate \
-DgroupId=com.yourname.pdfsummarizer \
-DartifactId=pdf-summarizer-service \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.4 -DinteractiveMode=false
```
3. Open the project in your IDE and run an initial `mvn clean compile` to verify setup
## Step 2: Configure Dependencies (pom.xml)
**Your Task:** Transform the basic Maven project into a Spring Boot application by modifying `pom.xml`:
### Required Changes:
1. **Parent Configuration:** Set Spring Boot as the parent with version 3.5.0
2. **Properties Block:** Define Java version (21) and Spring AI version (1.0.0)
3. **Dependency Management:** Import the Spring AI BOM to manage versions
4. **Core Dependencies:** Add these three essential starters:
- Web starter (for REST endpoints)
- Spring AI OpenAI starter (for LLM communication)
- PDF document reader (for PDF processing)
5. **Optional Enhancement:** Add Lombok for cleaner code
```xml
...Spring Boot 3.5.0...
21
1.0.0
...spring-ai-bom...
spring-boot-starter-web
spring-ai-openai-spring-boot-starter
spring-ai-pdf-document-reader
lombok
```
**Verification:** `mvn clean package` should complete without errors.
## Step 3: Application Configuration
**Your Task:** Create `src/main/resources/application.yml` with proper Spring AI configuration.
### Configuration Requirements:
1. **Server Settings:** Configure the application port
2. **Multipart Configuration:** Set appropriate file size limits for PDF uploads
3. **Spring AI OpenAI Settings:** Configure four key properties:
- `base-url`: Where is Docker Model Runner listening? (Hint: localhost with a specific port and path)
- `api-key`: What dummy value works for local usage?
- `model`: Which model did you download in Step 0?
- `temperature`: What value gives consistent summaries? (0.0-1.0 range)
```yaml
server:
port: 8080
spring:
servlet:
multipart:
max-file-size: 20MB
ai:
openai:
base-url: http://localhost:12434/
api-key: dummy
model: ai/istral
temperature: 0.0
```
**Research Required:**
- What port does Docker Model Runner use by default?
- What's the correct API endpoint path for OpenAI-compatible APIs?
- How does temperature affect LLM output consistency?
## Step 4: Core Business Logic - Service Layer
**Your Task:** Create a `PdfSummarizationService` class that orchestrates the summarization process.
### Class Structure:
```java
@Service
@RequiredArgsConstructor
public class PdfSummarizationService {
private final ChatModel chatModel;
public String summarize(MultipartFile pdf) throws IOException {
// TODO 1: validate pdf (size, emptiness)
// TODO 2: use PagePdfDocumentReader to pull List
// TODO 3: loop over pages → ask LLM for 2-3 sentence summary each
// Hint: new ChatClient(chatModel).call("Prompt" + pageContent)
// TODO 4: combine page summaries → ask LLM again for global summary
// Return final summary
return null; // placeholder
}
}
```
### Implementation Strategy:
1. **Input Validation:** Check if the file is valid and not empty
2. **PDF Processing:** Use `PagePdfDocumentReader` to extract text from each page
3. **Page Summarization:** Create individual summaries for each page using the LLM
4. **Global Summarization:** Combine page summaries into a comprehensive document summary
### Key Classes to Research:
- `ChatClient`: How do you build one from a `ChatModel`?
- `PagePdfDocumentReader`: What constructor parameters does it need?
- `Document`: How do you extract text content?
- `InputStreamResource`: How do you create one from a `MultipartFile`?
**Design Questions:**
- Why summarize page-by-page instead of the entire document at once?
- What happens if a PDF has no readable text?
- How should you handle very large PDFs?
**Prompt Engineering Tips:**
- Be specific about desired summary length
- Ask for key points and main ideas
## Step 5: REST API Layer - Controller
**Your Task:** Create a REST controller that exposes your summarization service.
### Class Structure:
```java
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class SummarizationController {
private final PdfSummarizationService service;
@PostMapping("/summarize")
public ResponseEntity summarize(@RequestParam("file") MultipartFile file) {
// TODO: call service
return null;
}
}
```
### Controller Requirements:
1. **Annotations:** Use appropriate Spring annotations for REST endpoints
2. **Endpoint Mapping:** Map to `/api/summarize` with POST method
3. **File Handling:** Accept multipart file uploads
4. **Error Handling:** Return appropriate HTTP status codes
5. **Response Format:** Return plain text summaries
### Implementation Considerations:
- What `@RequestMapping` configuration do you need?
- How do you handle `MultipartFile` parameters?
- What should happen when summarization fails?
- Should you return `ResponseEntity` or plain `String`?
## Step 6: Application Bootstrap
**Your Task:** Replace the default `App.java` with a proper Spring Boot application class.
### Class Structure:
```java
@SpringBootApplication
public class PdfSummarizerApplication {
public static void main(String[] args) { SpringApplication.run(PdfSummarizerApplication.class, args); }
}
```
*(This one is boilerplate; left intact so the app actually starts.)*
## Step 7: Local Testing & Debugging
**Your Task:** Get everything running and test the complete workflow.
### Testing Checklist:
1. **Verify Model Runner:** Confirm Docker Model Runner is active
2. **Start Application:** Use Maven to run your Spring Boot app
3. **Test Endpoint:** Use curl or Postman to send a PDF file
### Sample Test Command Structure:
```bash
# You'll need to construct the proper curl command
curl -F file=@your-test.pdf http://localhost:YOUR_PORT/YOUR_ENDPOINT
```
**Troubleshooting Guide:**
- `ResourceAccessException`: Check Docker Model Runner status and base-url configuration
- `404 Not Found`: Verify your controller mappings and component scanning
- `400 Bad Request`: Check file upload configuration and request format
- Empty response: Examine your service logic and LLM prompts
**Testing Tips:**
- Start with a small, simple PDF
- Check application logs for detailed error information
- Verify each step independently (PDF reading, LLM calls, etc.)
## Step 8: Containerization with Docker Compose
**Your Task:** Package your application for easy deployment.
### Docker Setup:
1. **Initialize Docker:** Use `docker init` to generate Docker configuration
2. **Configure Environment:** Set environment variables for container-to-host communication
3. **Network Configuration:** Ensure the containerized app can reach Docker Model Runner on the host
### Key Considerations:
- What base URL should the containerized app use to reach the host?
- How do you override Spring configuration with environment variables?
- What port mapping do you need in Docker Compose?
## Success Criteria
**Functional Requirements:**
- Application starts without errors
- PDF files can be uploaded and processed
- Summaries are generated and returned
- Local LLM integration works correctly
**Technical Requirements:**
- Proper Spring Boot project structure
- Clean separation of concerns (Controller → Service → AI)
- Appropriate error handling
- Containerized deployment option
**Learning Outcomes:**
- Understanding of Spring AI framework
- Experience with local LLM deployment
- REST API development skills
- Docker containerization knowledge
> Remember: The goal is to understand each component and how they work together. Don't hesitate to experiment, break things, and fix them – that's how real learning happens!