Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -287,4 +287,5 @@ target/
# Package manager files
package-lock.json
yarn.lock
pnpm-lock.yaml
pnpm-lock.yaml
任务.txt
126 changes: 126 additions & 0 deletions CANDIDATE_README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# AI Meeting Digest - Candidate Submission

## 1. Technology Choices

* **Frontend:** Vue.js 3 with Element Plus UI library
* **Backend:** Java Spring Boot with Spring WebFlux for reactive programming
* **Database:** MongoDB
* **AI Service:** Google Gemini API

### Why This Stack?

I chose this modern full-stack combination for several reasons:

- **Vue.js 3** provides excellent developer experience with its composition API and reactive system, paired with Element Plus for professional UI components
- **Spring Boot with WebFlux** enables both traditional REST APIs and reactive streaming capabilities needed for real-time AI response streaming
- **MongoDB** offers flexible document storage perfect for meeting summaries with varying structures
- **Google Gemini API** provides reliable AI text generation with streaming support and generous free tier

## 2. How to Run the Project

### Prerequisites
- Java 17 or higher
- Node.js 16+ and npm/yarn
- MongoDB instance (configured for 192.168.0.49:29001)

### Backend Setup
```bash
cd backend
# Run the Spring Boot application
./mvnw spring-boot:run
# Or: mvn spring-boot:run
```

### Frontend Setup
```bash
cd frontend
npm install
npm run serve
```

### Database Setup
The application will automatically connect to the configured MongoDB instance at 192.168.0.49:29001 and create the `meeting_summary` database if it doesn't exist.

### Access the Application
- Frontend: http://localhost:8081
- Backend API: http://localhost:8080

## 3. Design Decisions & Trade-offs

### Architecture Decisions

1. **Reactive Programming with WebFlux**: Implemented streaming responses using Spring WebFlux's `Flux` to handle real-time AI generation. This provides better user experience but adds complexity.

2. **Dual API Approach**: Created both traditional REST endpoints (`/api/summaries`) and streaming endpoints (`/api/summaries/stream`) to support both standard and real-time generation modes.

3. **Unique Public IDs**: Each summary gets a UUID-based public ID for secure sharing without exposing internal database IDs.

4. **Structured Summary Format**: Designed the AI prompt to return structured JSON with three specific sections: overview, key decisions, and action items.

### Implemented Features

#### Core Features 
- Clean, responsive UI with textarea for transcript input
- "Generate Digest" button with loading states
- Structured summary display (overview, decisions, action items)
- History view of all past summaries
- Database persistence of transcripts and summaries

#### Bonus Features 
- **Shareable Digest Links**: Each summary has a unique public URL (`/summary/:publicId`)
- **Real-time Streaming Response**: Implemented Server-Sent Events for word-by-word AI response streaming

### Trade-offs Made

1. **Chinese UI**: Implemented the interface in Chinese to demonstrate localization capability, though English would be more universal.

2. **Simple Error Handling**: Basic error handling with user-friendly messages, but could be more sophisticated for production.

3. **MongoDB Schema**: Chose flexible document structure over strict relational schema for easier summary format evolution.

4. **Streaming Parsing**: The streaming response parsing is somewhat fragile - relies on JSON extraction from streamed text.

### What I'd Do With More Time

- Add comprehensive unit and integration tests
- Implement user authentication and authorization
- Add summary editing and deletion capabilities
- Improve streaming response parsing robustness
- Add summary search and filtering
- Implement summary export to PDF/Word formats
- Add analytics and usage tracking
- Implement summary categorization and tagging

## 4. AI Usage Log

I extensively used AI programming assistants (Claude) throughout this project:

### Backend Development
- **Spring Boot Setup**: Used AI to generate the initial project structure and Maven dependencies
- **Reactive Programming**: Got help implementing WebFlux streaming endpoints, particularly the `Flux<String>` return types
- **Gemini Integration**: AI helped with HTTP client configuration and JSON request/response handling
- **Database Modeling**: Assistance with MongoDB repository setup and entity relationships

### Frontend Development
- **Vue.js 3 Components**: AI helped with Vue composition API patterns and Element Plus component integration
- **Streaming Implementation**: Got significant help implementing the fetch-based streaming response handling
- **CSS Styling**: AI assisted with responsive layout and professional styling
- **State Management**: Help with reactive data binding and component state management

### API Integration
- **CORS Configuration**: AI helped resolve cross-origin issues between frontend and backend
- **Error Handling**: Assistance with proper error propagation and user feedback
- **Stream Processing**: Significant help parsing Server-Sent Events format in the frontend

### Prompt Engineering
- **Gemini Prompt Design**: AI helped craft the prompt to ensure consistent JSON output format from Gemini API
- **Response Parsing**: Assistance with robust JSON extraction from AI responses

### Key AI Contributions
- Approximately 60% of boilerplate code generation
- 80% of complex reactive programming patterns
- 90% of streaming implementation logic
- 70% of error handling patterns
- 50% of UI component structure

The AI assistance was crucial for implementing the streaming features, which I hadn't worked with extensively before. It helped me understand WebFlux reactive patterns and frontend streaming consumption patterns that would have taken much longer to learn independently.
131 changes: 131 additions & 0 deletions backend/meeting-summary.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="UTF-8"?>
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Spring" name="Spring">
<configuration />
</facet>
<facet type="web" name="Web">
<configuration>
<webroots />
</configuration>
</facet>
</component>
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_13">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-actuator:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:3.2.0" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.4.11" level="project" />
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.4.11" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-to-slf4j:2.21.1" level="project" />
<orderEntry type="library" name="Maven: org.apache.logging.log4j:log4j-api:2.21.1" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:2.0.9" level="project" />
<orderEntry type="library" name="Maven: jakarta.annotation:jakarta.annotation-api:2.1.1" level="project" />
<orderEntry type="library" name="Maven: org.yaml:snakeyaml:2.2" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator-autoconfigure:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator:3.2.0" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.15.3" level="project" />
<orderEntry type="library" name="Maven: io.micrometer:micrometer-observation:1.12.0" level="project" />
<orderEntry type="library" name="Maven: io.micrometer:micrometer-commons:1.12.0" level="project" />
<orderEntry type="library" name="Maven: io.micrometer:micrometer-jakarta9:1.12.0" level="project" />
<orderEntry type="library" name="Maven: io.micrometer:micrometer-core:1.12.0" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.hdrhistogram:HdrHistogram:2.1.12" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.latencyutils:LatencyUtils:2.0.3" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:3.2.0" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.15.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.15.3" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:10.1.16" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:10.1.16" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-web:6.1.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-beans:6.1.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webmvc:6.1.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-aop:6.1.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-context:6.1.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-expression:6.1.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-mongodb:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-sync:4.11.1" level="project" />
<orderEntry type="library" name="Maven: org.mongodb:bson:4.11.1" level="project" />
<orderEntry type="library" name="Maven: org.mongodb:mongodb-driver-core:4.11.1" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.mongodb:bson-record-codec:4.11.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-mongodb:4.2.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-tx:6.1.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework.data:spring-data-commons:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:2.0.9" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-validation:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:10.1.16" level="project" />
<orderEntry type="library" name="Maven: org.hibernate.validator:hibernate-validator:8.0.1.Final" level="project" />
<orderEntry type="library" name="Maven: jakarta.validation:jakarta.validation-api:3.0.2" level="project" />
<orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.5.3.Final" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml:classmate:1.6.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-webflux:3.2.0" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-reactor-netty:3.2.0" level="project" />
<orderEntry type="library" name="Maven: io.projectreactor.netty:reactor-netty-http:1.1.13" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec-http:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-common:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-buffer:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-transport:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-handler:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec-http2:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-resolver-dns:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-resolver:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec-dns:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-resolver-dns-native-macos:osx-x86_64:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-resolver-dns-classes-macos:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-transport-native-epoll:linux-x86_64:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-transport-native-unix-common:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-transport-classes-epoll:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.projectreactor.netty:reactor-netty-core:1.1.13" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-handler-proxy:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: io.netty:netty-codec-socks:4.1.101.Final" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-webflux:6.1.1" level="project" />
<orderEntry type="library" name="Maven: io.projectreactor:reactor-core:3.6.0" level="project" />
<orderEntry type="library" name="Maven: org.reactivestreams:reactive-streams:1.0.4" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.15.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.15.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.15.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:3.2.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:3.2.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:3.2.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.8.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: jakarta.xml.bind:jakarta.xml.bind-api:4.0.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: jakarta.activation:jakarta.activation-api:2.1.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.5.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:2.5.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:9.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:3.24.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy:1.14.10" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.awaitility:awaitility:4.2.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest:2.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter:5.10.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-api:5.10.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.opentest4j:opentest4j:1.3.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-commons:1.10.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.apiguardian:apiguardian-api:1.1.2" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-params:5.10.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.jupiter:junit-jupiter-engine:5.10.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.junit.platform:junit-platform-engine:1.10.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:5.7.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: net.bytebuddy:byte-buddy-agent:1.14.10" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:3.3" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-junit-jupiter:5.7.0" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.5.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-core:6.1.1" level="project" />
<orderEntry type="library" name="Maven: org.springframework:spring-jcl:6.1.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:6.1.1" level="project" />
<orderEntry type="library" scope="TEST" name="Maven: org.xmlunit:xmlunit-core:2.9.1" level="project" />
</component>
</module>
Loading