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
98 changes: 66 additions & 32 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,38 +1,72 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
```
# Compiled and build artifacts
*.class
*.o
*.obj
*.exe
*.dll
*.so
*.a
*.out

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
# Dependencies
target/
.m2/
.gradle/
node_modules/
venv/
.venv/
__pycache__/
.mypy_cache/
.pytest_cache/

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
# Logs and temp files
*.log
*.tmp
*.swp
*.swo

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
# Environment
.env
.env.local
*.env.*

### VS Code ###
# Editors
.vscode/
.idea/
*.swp
*.swo

# OS generated files
.DS_Store
Thumbs.db

# Coverage reports
coverage/
htmlcov/
.coverage

*.mvn
*.sample
mvnw
*.cmd
# Package files
*.zip
*.gz
*.tar
*.tgz
*.bz2
*.xz
*.7z
*.rar
*.zst
*.lz4
*.lzh
*.cab
*.arj
*.rpm
*.deb
*.Z
*.lz
*.lzo
*.tar.gz
*.tar.bz2
*.tar.xz
*.tar.zst
```
27 changes: 25 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,36 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Spring AI dependencies -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-dashscope-spring-boot-starter</artifactId>
<artifactId>spring-ai-transformers-spring-boot-starter</artifactId>
</dependency>
<!-- For custom Qwen integration -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-deepseek-spring-boot-starter</artifactId>
<artifactId>spring-ai-core</artifactId>
</dependency>
<!-- Additional dependencies for MCP and communication -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/com/ai/agent/SmartAgentApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.ai.agent;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SmartAgentApplication {

public static void main(String[] args) {
SpringApplication.run(SmartAgentApplication.class, args);
}

}
109 changes: 109 additions & 0 deletions src/main/java/com/ai/agent/controller/McpBaiduMapsController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.ai.agent.controller;

import com.ai.agent.mcp.McpServer;
import com.ai.agent.mcp.model.McpRequest;
import com.ai.agent.mcp.model.McpResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/baidu-maps")
public class McpBaiduMapsController {

@Autowired
private McpServer sseMcpServer;

// Initialize MCP handlers for Baidu Maps service
@javax.annotation.PostConstruct
public void initBaiduMapsMcpHandlers() {
// Handler for geocoding requests
sseMcpServer.registerHandler("baidu/maps/geocode", request -> {
Map<String, Object> params = (Map<String, Object>) request.getParams();
String address = (String) params.get("address");
return geocodeAddress(address);
});

// Handler for reverse geocoding requests
sseMcpServer.registerHandler("baidu/maps/reverse-geocode", request -> {
Map<String, Object> params = (Map<String, Object>) request.getParams();
Double lat = ((Number) params.get("latitude")).doubleValue();
Double lng = ((Number) params.get("longitude")).doubleValue();
return reverseGeocode(lat, lng);
});

// Handler for place search
sseMcpServer.registerHandler("baidu/maps/search-place", request -> {
Map<String, Object> params = (Map<String, Object>) request.getParams();
String query = (String) params.get("query");
String city = (String) params.get("city");
return searchPlace(query, city);
});
}

@PostMapping("/geocode")
public Mono<Map<String, Object>> geocode(@RequestBody Map<String, String> request) {
String address = request.get("address");
return Mono.just(geocodeAddress(address));
}

@PostMapping("/reverse-geocode")
public Mono<Map<String, Object>> reverseGeocode(@RequestBody Map<String, Object> request) {
Double lat = Double.valueOf(request.get("latitude").toString());
Double lng = Double.valueOf(request.get("longitude").toString());
return Mono.just(reverseGeocode(lat, lng));
}

@PostMapping("/search")
public Mono<Map<String, Object>> searchPlace(@RequestBody Map<String, String> request) {
String query = request.get("query");
String city = request.get("city");
return Mono.just(searchPlace(query, city));
}

// Mock implementations of Baidu Maps API calls
private Map<String, Object> geocodeAddress(String address) {
Map<String, Object> result = new HashMap<>();
result.put("status", "success");
result.put("address", address);
result.put("location", Map.of(
"lat", 39.9042,
"lng", 116.4074
));
result.put("formatted_address", "北京市东城区天安门广场");
return result;
}

private Map<String, Object> reverseGeocode(Double lat, Double lng) {
Map<String, Object> result = new HashMap<>();
result.put("status", "success");
result.put("latitude", lat);
result.put("longitude", lng);
result.put("address", "北京市东城区天安门广场");
result.put("formatted_address", "北京市东城区天安门广场");
return result;
}

private Map<String, Object> searchPlace(String query, String city) {
Map<String, Object> result = new HashMap<>();
result.put("status", "success");
result.put("query", query);
result.put("city", city);
result.put("places", new Object[] {
Map.of(
"name", "天安门广场",
"address", "北京市东城区天安门广场",
"location", Map.of("lat", 39.9042, "lng", 116.4074)
),
Map.of(
"name", "故宫博物院",
"address", "北京市东城区景山前街4号",
"location", Map.of("lat", 39.9163, "lng", 116.3972)
)
});
return result;
}
}
96 changes: 96 additions & 0 deletions src/main/java/com/ai/agent/controller/SmartAgentController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.ai.agent.controller;

import com.ai.agent.mcp.McpClient;
import com.ai.agent.mcp.model.McpRequest;
import com.ai.agent.service.Qwen3Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api/agent")
public class SmartAgentController {

@Autowired
private Qwen3Service qwen3Service;

@Autowired
private McpClient sseMcpClient;

@PostMapping("/chat")
public Map<String, Object> chat(@RequestBody Map<String, String> request) {
String message = request.get("message");
String response = qwen3Service.generateText(message);

Map<String, Object> result = new HashMap<>();
result.put("input", message);
result.put("output", response);
result.put("model", "Qwen3-32B");

return result;
}

@GetMapping("/stream-chat")
public SseEmitter streamChat(@RequestParam String message) {
SseEmitter emitter = new SseEmitter(Long.MAX_VALUE);

try {
Flux<org.springframework.ai.chat.model.ChatResponse> stream = qwen3Service.streamChat(message);

stream.subscribe(
response -> {
try {
emitter.send(SseEmitter.event()
.name("chunk")
.data(response.getResult().getOutput().getContent()));
} catch (IOException e) {
emitter.completeWithError(e);
}
},
error -> emitter.completeWithError(error),
() -> {
try {
emitter.send(SseEmitter.event().name("complete").data("Stream completed"));
emitter.complete();
} catch (IOException e) {
emitter.completeWithError(e);
}
}
);
} catch (Exception e) {
emitter.completeWithError(e);
}

return emitter;
}

@PostMapping("/mcp-request")
public Map<String, Object> mcpRequest(@RequestBody Map<String, Object> request) {
String method = (String) request.get("method");
Object params = request.get("params");

McpRequest mcpRequest = new McpRequest(method, "req-" + System.currentTimeMillis(), params);
com.ai.agent.mcp.model.McpResponse response = sseMcpClient.sendRequest(mcpRequest);

Map<String, Object> result = new HashMap<>();
result.put("request", mcpRequest);
result.put("response", response);

return result;
}

@GetMapping("/health")
public Map<String, String> health() {
Map<String, String> health = new HashMap<>();
health.put("status", "healthy");
health.put("model", "Qwen3-32B");
health.put("framework", "vLLM/MindIE");
health.put("mcp", "SSE/STDIO");
return health;
}
}
12 changes: 12 additions & 0 deletions src/main/java/com/ai/agent/mcp/McpClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.ai.agent.mcp;

import com.ai.agent.mcp.model.McpRequest;
import com.ai.agent.mcp.model.McpResponse;
import reactor.core.publisher.Flux;

public interface McpClient {
McpResponse sendRequest(McpRequest request);
Flux<McpResponse> sendStreamRequest(McpRequest request);
void connect();
void disconnect();
}
Loading