Foundry Local Spring Boot 教程 目录 前置条件 项目概述 代码解析 应用配置 (application.properties) 主应用类 (Application.java) AI 服务层 (FoundryLocalService.java) 项目依赖 (pom.xml) 整体工作流程 设置 Foundry Local 运行应用 预期输出 下一步 故障排除 前置条件 在开始本教程之前,请确保您已完成以下准备工作: 系统已安装 Java 21 或更高版本 使用 Maven 3.6+ 构建项目 已安装并运行 Foundry Local 安装 Foundry Local: 项目概述 该项目主要由以下四个组件组成: Application.
在开始本教程之前,请确保您已完成以下准备工作:
# Windows winget install Microsoft.FoundryLocal # macOS (after installing) foundry model run phi-3.5-mini
该项目主要由以下四个组件组成:
文件路径: src/main/resources/application.properties
foundry.local.base-url=http://localhost:5273/v1 foundry.local.model=Phi-3.5-mini-instruct-cuda-gpu:1
功能说明:
/v1 路径以兼容 OpenAI API。注意: Foundry Local 会动态分配端口,请使用 foundry service status 检查实际端口。:1)。使用 foundry model list 查看可用模型及其准确 ID。关键概念: Spring Boot 会自动加载这些配置,并通过 @Value 注解在应用中使用。
文件路径: src/main/java/com/example/Application.java
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication app = new SpringApplication(Application.class); app.setWebApplicationType(WebApplicationType.NONE); // No web server needed app.run(args); }
功能说明:
@SpringBootApplication 启用 Spring Boot 自动配置WebApplicationType.NONE 指定这是一个命令行应用,而不是 Web 服务器演示运行器:
@Bean public CommandLineRunner foundryLocalRunner(FoundryLocalService foundryLocalService) { return args -> { System.out.println("=== Foundry Local Demo ==="); System.out.println("Calling Foundry Local service..."); String testMessage = "Hello! Can you tell me what you are and what model you're running?"; System.out.println("Sending message: " + testMessage); String response = foundryLocalService.chat(testMessage); System.out.println("Response from Foundry Local:"); System.out.println(response); System.out.println("========================="); }; }
功能说明:
@Bean 创建由 Spring 管理的组件CommandLineRunner 在 Spring Boot 启动后运行代码foundryLocalService 通过 Spring 自动注入(依赖注入)文件路径: src/main/java/com/example/FoundryLocalService.java
@Service public class FoundryLocalService { @Value("${foundry.local.base-url:http://localhost:5273/v1}") private String baseUrl; @Value("${foundry.local.model:Phi-3.5-mini-instruct-cuda-gpu:1}") private String model;
功能说明:
@Service 表示该类提供业务逻辑@Value 从 application.properties 注入配置值:default-value 语法提供默认值,以防配置未设置@PostConstruct public void init() { this.openAIClient = OpenAIOkHttpClient.builder() .baseUrl(baseUrl) // Base URL already includes /v1 from configuration .apiKey("not-needed") // Local server doesn't need real API key .build(); }
功能说明:
@PostConstruct 在 Spring 创建服务后运行此方法application.properties 中的 base URL 已包含 /v1 以兼容 OpenAI APIpublic String chat(String message) { try { ChatCompletionCreateParams params = ChatCompletionCreateParams.builder() .model(model) // Which AI model to use .addUserMessage(message) // Your question/prompt .maxCompletionTokens(150) // Limit response length .temperature(0.7) // Control creativity (0.0-1.0) .build(); ChatCompletion chatCompletion = openAIClient.chat().completions().create(params); // Extract the AI's response from the API result if (chatCompletion.choices() != null && !chatCompletion.choices().isEmpty()) { return chatCompletion.choices().get(0).message().content().orElse("No response found"); } return "No response content found"; } catch (Exception e) { throw new RuntimeException("Error calling chat completion: " + e.getMessage(), e); } }
功能说明:
model: 指定使用的 AI 模型(必须与 foundry model list 中的 ID 完全匹配)addUserMessage: 将用户消息添加到对话中maxCompletionTokens: 限制响应长度(节省资源)temperature: 控制随机性(0.0 = 确定性,1.0 = 创造性)关键依赖:
<!-- Spring Boot - Application framework --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>${spring-boot.version}</version> </dependency> <!-- OpenAI Java SDK - For AI API calls --> <dependency> <groupId>com.openai</groupId> <artifactId>openai-java</artifactId> <version>2.12.0</version> </dependency> <!-- Jackson - JSON processing --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.17.0</version> </dependency>
功能说明:
运行应用时的完整流程如下:
application.propertiesFoundryLocalService 并注入配置值@PostConstruct 初始化 OpenAI 客户端以连接到 Foundry LocalCommandLineRunner 在启动后执行foundryLocalService.chat() 发送测试消息按照以下步骤设置 Foundry Local:
安装 Foundry Local,参考 前置条件 部分的说明。
检查动态分配的端口。Foundry Local 启动时会自动分配端口。使用以下命令查看端口:
foundry service status
可选: 如果您希望使用特定端口(例如 5273),可以手动配置:
foundry service set --port 5273
下载您想使用的 AI 模型,例如 phi-3.5-mini,使用以下命令:
foundry model run phi-3.5-mini
配置 application.properties 文件以匹配您的 Foundry Local 设置:
base-url 中的端口(步骤 2 中获取),确保末尾包含 /v1foundry model list 检查)示例:
foundry.local.base-url=http://localhost:5273/v1 foundry.local.model=Phi-3.5-mini-instruct-cuda-gpu:1
foundry model run phi-3.5-mini
mvn clean package java -jar target/foundry-local-spring-boot-0.0.1-SNAPSHOT.jar
=== Foundry Local Demo === Calling Foundry Local service... Sending message: Hello! Can you tell me what you are and what model you're running? Response from Foundry Local: Hello! I'm Phi-3.5, a small language model created by Microsoft. I'm currently running as the Phi-3.5-mini-instruct model, which is designed to be helpful, harmless, and honest in my interactions. I can assist with a wide variety of tasks including answering questions, helping with analysis, creative writing, coding, and general conversation. Is there something specific you'd like help with today? =========================
更多示例,请参阅 第 04 章: 实用样例
"Connection refused" 或 "Service unavailable"
foundry model listfoundry service statusapplication.properties 中的端口,确保 URL 以 /v1 结尾foundry service set --port 5273foundry model run phi-3.5-mini"Model not found" 或 "404 Not Found" 错误
foundry model list 检查可用模型及其准确 IDapplication.properties 中的模型名称,确保完全匹配,包括版本号(例如 Phi-3.5-mini-instruct-cuda-gpu:1)base-url 包含 /v1 结尾: http://localhost:5273/v1foundry model run phi-3.5-mini"400 Bad Request" 错误
/v1: http://localhost:5273/v1foundry model list 中显示的完全匹配maxCompletionTokens()(而不是已弃用的 maxTokens())Maven 编译错误
java -versionmvn clean compile应用启动但无输出
http://localhost:5273/v1/models 或运行 foundry service status免责声明:
本文档使用AI翻译服务Co-op Translator进行翻译。尽管我们努力确保翻译的准确性,但请注意,自动翻译可能包含错误或不准确之处。应以原始语言的文档作为权威来源。对于关键信息,建议使用专业人工翻译。我们不对因使用此翻译而产生的任何误解或误读承担责任。