Java AI智能体实战:使用LangChain4j构建能使用工具的AI助手

简介: 随着AI技术的发展,AI智能体(Agent)能够通过使用工具来执行复杂任务,从而大幅扩展其能力边界。本文介绍如何在Java中使用LangChain4j框架构建一个能够使用外部工具的AI智能体。我们将通过一个具体示例——一个能获取天气信息和执行数学计算的AI助手,详细讲解如何定义工具、创建智能体并处理执行流程。本文包含完整的代码示例和架构说明,帮助Java开发者快速上手AI智能体的开发。

一、 引言:从被动响应到主动工具的AI智能体
传统的大模型应用通常仅限于文本生成和对话,而AI智能体则能够通过使用工具(如调用API、执行代码、查询数据库等)来主动完成现实世界中的任务。这种能力使得AI智能体能够处理更多样化的需求,例如订餐、查询天气、控制智能家居等。

LangChain4j是一个基于Java的AI应用开发框架,它提供了构建AI智能体所需的核心组件,包括工具抽象、智能体执行流程和记忆管理。通过LangChain4j,Java开发者可以轻松地构建出功能强大的AI智能体。

二、 项目搭建与依赖配置
首先,我们创建一个新的Spring Boot项目,并添加LangChain4j的相关依赖。

xml


0.29.0



org.springframework.boot
spring-boot-starter-web

<!-- LangChain4j 核心 -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j</artifactId>
    <version>${langchain4j.version}</version>
</dependency>

<!-- LangChain4j OpenAI 集成 -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-open-ai</artifactId>
    <version>${langchain4j.version}</version>
</dependency>

<!-- 用于处理JSON -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>


三、 定义工具(Tools)
工具是AI智能体扩展能力的关键。我们定义两个工具:一个用于获取天气,另一个用于执行数学计算。

  1. 天气工具

假设我们有一个获取天气的API,我们可以定义一个工具方法来调用这个API。

java
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

@Component
public class WeatherTool {

private final HttpClient httpClient;
private final ObjectMapper objectMapper;

public WeatherTool() {
    this.httpClient = HttpClient.newHttpClient();
    this.objectMapper = new ObjectMapper();
}

@Tool("获取指定城市的当前天气")
public String getWeather(@P("城市名称") String city) {
    try {
        // 这里使用模拟的天气API,实际应用中请替换为真实的API
        String apiUrl = "https://api.example.com/weather?city=" + city;
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(apiUrl))
                .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
        // 解析响应并返回天气信息
        // 假设返回的JSON结构为:{"city":"Beijing","temperature":"25","condition":"Sunny"}
        WeatherResponse weatherResponse = objectMapper.readValue(response.body(), WeatherResponse.class);
        return String.format("%s的天气是%s,温度%s摄氏度", city, weatherResponse.getCondition(), weatherResponse.getTemperature());
    } catch (Exception e) {
        return "无法获取天气信息:" + e.getMessage();
    }
}

private static class WeatherResponse {
    private String city;
    private String temperature;
    private String condition;

    // getters and setters
    public String getCity() { return city; }
    public void setCity(String city) { this.city = city; }
    public String getTemperature() { return temperature; }
    public void setTemperature(String temperature) { this.temperature = temperature; }
    public String getCondition() { return condition; }
    public void setCondition(String condition) { this.condition = condition; }
}

}

  1. 计算工具

我们还可以定义一个执行数学计算的工具。

java
import org.springframework.stereotype.Component;

@Component
public class CalculationTool {

@Tool("执行数学计算,例如:1+1,2*3,10/2")
public double calculate(@P("数学表达式") String expression) {
    try {
        // 这里使用简单的表达式计算,实际应用中可以使用更复杂的表达式解析库
        if (expression.contains("+")) {
            String[] parts = expression.split("\\+");
            return Double.parseDouble(parts[0]) + Double.parseDouble(parts[1]);
        } else if (expression.contains("-")) {
            String[] parts = expression.split("-");
            return Double.parseDouble(parts[0]) - Double.parseDouble(parts[1]);
        } else if (expression.contains("*")) {
            String[] parts = expression.split("\\*");
            return Double.parseDouble(parts[0]) * Double.parseDouble(parts[1]);
        } else if (expression.contains("/")) {
            String[] parts = expression.split("/");
            return Double.parseDouble(parts[0]) / Double.parseDouble(parts[1]);
        } else {
            return Double.parseDouble(expression);
        }
    } catch (Exception e) {
        throw new RuntimeException("计算失败,请检查表达式格式");
    }
}

}
四、 创建AI智能体
我们将使用LangChain4j的AiServices来创建一个智能体,并将上述工具赋予它。

java
import dev.langchain4j.service.AiServices;
import org.springframework.stereotype.Service;

@Service
public class AssistantService {

private final Assistant assistant;

public AssistantService(WeatherTool weatherTool, CalculationTool calculationTool) {
    // 创建AI智能体,并指定它可以使用哪些工具
    this.assistant = AiServices.builder(Assistant.class)
            .chatLanguageModel(OpenAiChatModel.builder()
                    .apiKey(System.getenv("OPENAI_API_KEY"))
                    .modelName("gpt-3.5-turbo")
                    .build())
            .tools(weatherTool, calculationTool)
            .build();
}

public String chat(String userMessage) {
    return assistant.chat(userMessage);
}

// 定义智能体接口
interface Assistant {
    String chat(String userMessage);
}

}
五、 提供REST API
我们创建一个控制器来暴露智能体的聊天接口。

java
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/assistant")
public class AssistantController {

private final AssistantService assistantService;

public AssistantController(AssistantService assistantService) {
    this.assistantService = assistantService;
}

@PostMapping("/chat")
public String chat(@RequestBody ChatRequest request) {
    return assistantService.chat(request.message());
}

public record ChatRequest(String message) {}

}
六、 测试智能体
启动应用后,我们可以使用curl或Postman进行测试。

示例1:询问天气

bash
curl -X POST http://localhost:8080/api/assistant/chat \
-H "Content-Type: application/json" \
-d '{"message": "北京今天的天气怎么样?"}'
智能体会调用天气工具,并返回类似:“北京的天气是晴天,温度25摄氏度”。

示例2:数学计算

bash
curl -X POST http://localhost:8080/api/assistant/chat \
-H "Content-Type: application/json" \
-d '{"message": "计算一下123乘以456等于多少?"}'
智能体会调用计算工具,并返回计算结果。

七、 高级特性:记忆和对话历史
为了让智能体在对话中记住上下文,我们可以为智能体添加记忆能力。

java
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;

@Service
public class AssistantService {

private final Assistant assistant;

public AssistantService(WeatherTool weatherTool, CalculationTool calculationTool) {
    // 创建带有记忆的智能体
    ChatMemory chatMemory = MessageWindowChatMemory.withMaxMessages(10);

    this.assistant = AiServices.builder(Assistant.class)
            .chatLanguageModel(OpenAiChatModel.builder()
                    .apiKey(System.getenv("OPENAI_API_KEY"))
                    .modelName("gpt-3.5-turbo")
                    .build())
            .tools(weatherTool, calculationTool)
            .chatMemory(chatMemory)
            .build();
}

// ... 其他代码不变

}
现在,智能体可以记住之前的对话内容。例如,用户可以先问:“北京今天的天气怎么样?”,然后接着问:“那上海呢?”,智能体会知道用户是在询问上海的天气。

八、 总结
通过LangChain4j,Java开发者可以相对轻松地构建出能够使用工具的AI智能体。本文演示了如何定义工具、创建智能体并处理对话记忆。这种模式可以扩展到更复杂的场景,例如让智能体调用数据库、发送邮件、控制设备等。

AI智能体的开发仍处于快速发展阶段,LangChain4j等框架正在不断丰富其功能。随着技术的成熟,我们有望看到更多由AI智能体驱动的创新应用。

标题:Java与大模型推理优化:使用ONNX Runtime实现本地化部署
摘要: 随着大模型应用从云端向边缘扩展,本地化部署成为保护数据隐私、降低延迟和减少API成本的关键需求。本文深入探讨如何在Java生态中利用ONNX Runtime实现大模型的本地推理优化。我们将完整展示从模型转换、Java集成到性能调优的全过程,重点介绍如何在生产环境中部署和优化开源大模型,为构建高性价比、数据安全的AI应用提供切实可行的技术方案。

文章内容
一、 引言:从云端API到本地推理的范式转变
依赖云端大模型API的方案存在明显局限:数据隐私风险、网络延迟依赖、持续成本压力以及定制化困难。越来越多的场景需要将模型部署到本地环境:

金融和医疗行业:敏感数据无法出域

工业物联网:网络不稳定的边缘环境

高并发应用:API调用成本随规模线性增长

实时系统:网络往返延迟不可接受

ONNX(Open Neural Network Exchange)作为开放的模型格式标准,结合ONNX Runtime的高性能推理引擎,为Java开发者提供了理想的本地化解决方案。本文将基于一个具体的开源模型(如Microsoft的Phi-3-mini),演示完整的本地化部署流程。

二、 技术栈选择与环境准备

  1. 核心组件

ONNX Runtime:微软开源的高性能推理引擎,支持多种硬件后端

Hugging Face Transformers:模型转换和预处理工具

Spring Boot:应用框架

Apache Commons IO:文件处理工具

  1. 项目依赖配置

xml


1.17.0
3.2.0



org.springframework.boot
spring-boot-starter-web
${spring-boot.version}

<!-- ONNX Runtime Core -->
<dependency>
    <groupId>com.microsoft.onnxruntime</groupId>
    <artifactId>onnxruntime</artifactId>
    <version>${onnxruntime.version}</version>
</dependency>

<!-- 用于文本预处理 -->
<dependency>
    <groupId>com.huggingface</groupId>
    <artifactId>tokenizers</artifactId>
    <version>0.14.0</version>
</dependency>

<!-- 工具库 -->
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.14.0</version>
</dependency>


三、 模型准备与转换

  1. 从Hugging Face获取并转换模型

首先需要将预训练模型转换为ONNX格式:

python

convert_to_onnx.py - Python转换脚本

from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

def convert_model_to_onnx():
model_name = "microsoft/Phi-3-mini-4k-instruct"

# 加载原始模型和tokenizer
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    torch_dtype=torch.float16,  # 使用半精度减少模型大小
    device_map="auto",
    trust_remote_code=True
)

# 准备示例输入
sample_input = "Hello, how are you?"
inputs = tokenizer(sample_input, return_tensors="pt")

# 导出为ONNX格式
torch.onnx.export(
    model,
    tuple(inputs.values()),
    "phi-3-mini.onnx",
    input_names=['input_ids', 'attention_mask'],
    output_names=['logits'],
    dynamic_axes={
        'input_ids': {0: 'batch_size', 1: 'sequence_length'},
        'attention_mask': {0: 'batch_size', 1: 'sequence_length'},
        'logits': {0: 'batch_size', 1: 'sequence_length'}
    },
    opset_version=14,
    do_constant_folding=True
)

# 保存tokenizer配置
tokenizer.save_pretrained("./tokenizer")

if name == "main":
convert_model_to_onnx()

  1. 模型优化

使用ONNX Runtime的优化工具对模型进行图优化:

bash

使用ONNX Runtime优化工具

python -m onnxruntime.tools.optimize_onnx --input phi-3-mini.onnx --output phi-3-mini-optimized.onnx --opt_level 1
四、 Java推理引擎实现

  1. ONNX Runtime服务封装

创建核心的推理服务类:

java
// ONNXModelService.java
@Component
@Slf4j
public class ONNXModelService implements AutoCloseable {

private final OrtEnvironment environment;
private final OrtSession session;
private final Map<String, OnnxTensor> allocatedTensors;
private final Tokenizer tokenizer;

public ONNXModelService(@Value("${model.path}") String modelPath,
                       @Value("${tokenizer.path}") String tokenizerPath) throws Exception {
    this.environment = OrtEnvironment.getEnvironment();
    this.allocatedTensors = new ConcurrentHashMap<>();

    // 配置会话选项
    OrtSession.SessionOptions sessionOptions = new OrtSession.SessionOptions();

    // 根据硬件配置提供者(CPU/CUDA/CoreML等)
    String[] availableProviders = OrtSession.getAvailableProviders();
    if (Arrays.asList(availableProviders).contains("CUDAExecutionProvider")) {
        sessionOptions.addCUDA(0); // 使用GPU
        log.info("使用CUDA执行提供者");
    } else {
        sessionOptions.setOptimizationLevel(OrtSession.SessionOptions.OptLevel.ALL_OPT);
        sessionOptions.setExecutionMode(OrtSession.SessionOptions.ExecutionMode.SEQUENTIAL);
        log.info("使用CPU执行提供者");
    }

    // 加载ONNX模型
    this.session = environment.createSession(modelPath, sessionOptions);

    // 加载tokenizer
    this.tokenizer = Tokenizer.fromFile(Paths.get(tokenizerPath, "tokenizer.json"));

    log.info("ONNX模型加载完成,输入: {}, 输出: {}", 
             session.getInputInfo().keySet(), 
             session.getOutputInfo().keySet());
}

/**
 * 文本生成推理
 */
public String generateText(String prompt, int maxLength, double temperature) {
    long startTime = System.currentTimeMillis();
    try {
        // 1. 文本编码
        Encoding encoding = tokenizer.encode(prompt, true);
        long[] inputIds = encoding.getIds();
        long[] attentionMask = encoding.getAttentionMask();

        // 2. 准备模型输入
        Map<String, OnnxTensor> inputs = prepareModelInputs(inputIds, attentionMask);

        // 3. 执行推理(自回归生成)
        String generatedText = autoregressiveGenerate(inputs, maxLength, temperature);

        long duration = System.currentTimeMillis() - startTime;
        log.info("推理完成,耗时: {}ms, 生成长度: {}", duration, generatedText.length());

        return generatedText;

    } catch (Exception e) {
        log.error("推理过程失败", e);
        throw new RuntimeException("模型推理失败", e);
    }
}

private Map<String, OnnxTensor> prepareModelInputs(long[] inputIds, long[] attentionMask) 
        throws OrtException {

    long[][] inputIdsArray = {inputIds};
    long[][] attentionMaskArray = {attentionMask};

    OnnxTensor inputIdsTensor = OnnxTensor.createTensor(environment, inputIdsArray);
    OnnxTensor attentionMaskTensor = OnnxTensor.createTensor(environment, attentionMaskArray);

    // 缓存张量以便后续释放
    String inputIdsKey = "input_ids_" + System.currentTimeMillis();
    String attentionMaskKey = "attention_mask_" + System.currentTimeMillis();
    allocatedTensors.put(inputIdsKey, inputIdsTensor);
    allocatedTensors.put(attentionMaskKey, attentionMaskTensor);

    return Map.of(
        "input_ids", inputIdsTensor,
        "attention_mask", attentionMaskTensor
    );
}

private String autoregressiveGenerate(Map<String, OnnxTensor> initialInputs, 
                                     int maxLength, double temperature) 
        throws OrtException {

    List<Long> allGeneratedIds = new ArrayList<>();
    Map<String, OnnxTensor> currentInputs = new HashMap<>(initialInputs);

    for (int step = 0; step < maxLength; step++) {
        // 执行单步推理
        OrtSession.Result results = session.run(currentInputs);

        try (OnnxTensor logitsTensor = (OnnxTensor) results.get(0)) {
            float[][][] logits = (float[][][]) logitsTensor.getValue();

            // 获取最后一个token的logits
            float[] lastTokenLogits = logits[0][logits[0].length - 1];

            // 应用温度采样
            long nextTokenId = sampleWithTemperature(lastTokenLogits, temperature);

            // 检查结束标记(假设结束标记为2)
            if (nextTokenId == 2) {
                break;
            }

            allGeneratedIds.add(nextTokenId);

            // 更新输入用于下一步
            updateInputsForNextStep(currentInputs, nextTokenId);
        }
    }

    // 解码生成的token
    long[] generatedIds = allGeneratedIds.stream()
            .mapToLong(Long::longValue)
            .toArray();

    return tokenizer.decode(generatedIds);
}

private long sampleWithTemperature(float[] logits, double temperature) {
    // 应用温度变换
    double[] scaledLogits = Arrays.stream(logits)
            .mapToDouble(logit -> logit / temperature)
            .toArray();

    // Softmax计算概率
    double[] probabilities = softmax(scaledLogits);

    // 基于概率分布采样
    return weightedRandomSample(probabilities);
}

private double[] softmax(double[] logits) {
    double maxLogit = Arrays.stream(logits).max().orElse(0);
    double[] expLogits = Arrays.stream(logits)
            .map(logit -> Math.exp(logit - maxLogit))
            .toArray();
    double sum = Arrays.stream(expLogits).sum();
    return Arrays.stream(expLogits).map(exp -> exp / sum).toArray();
}

private long weightedRandomSample(double[] probabilities) {
    double random = Math.random();
    double cumulative = 0.0;

    for (int i = 0; i < probabilities.length; i++) {
        cumulative += probabilities[i];
        if (random <= cumulative) {
            return i;
        }
    }

    return probabilities.length - 1;
}

private void updateInputsForNextStep(Map<String, OnnxTensor> currentInputs, long nextTokenId) 
        throws OrtException {

    // 释放之前的张量
    currentInputs.values().forEach(tensor -> {
        try {
            tensor.close();
        } catch (Exception e) {
            log.warn("释放张量失败", e);
        }
    });

    // 构建新的输入(只包含新生成的token)
    long[][] newInputIds = {
  {nextTokenId}};
    long[][] newAttentionMask = {
  {1}};

    OnnxTensor newInputIdsTensor = OnnxTensor.createTensor(environment, newInputIds);
    OnnxTensor newAttentionMaskTensor = OnnxTensor.createTensor(environment, newAttentionMask);

    currentInputs.put("input_ids", newInputIdsTensor);
    currentInputs.put("attention_mask", newAttentionMaskTensor);
}

@Override
public void close() throws Exception {
    // 清理所有分配的张量
    allocatedTensors.values().forEach(tensor -> {
        try {
            tensor.close();
        } catch (Exception e) {
            log.warn("关闭张量时出错", e);
        }
    });
    allocatedTensors.clear();

    if (session != null) {
        session.close();
    }
    if (environment != null) {
        environment.close();
    }
}

}

  1. 配置和性能监控

java
// ModelConfig.java
@Configuration
@ConfigurationProperties(prefix = "ai.model")
@Data
public class ModelConfig {
private String modelPath;
private String tokenizerPath;
private int maxGenerationLength = 512;
private double temperature = 0.7;
private boolean enableBenchmark = false;
}

// ModelMetrics.java
@Component
public class ModelMetrics {
private final MeterRegistry meterRegistry;
private final Timer inferenceTimer;
private final Counter tokenCounter;

public ModelMetrics(MeterRegistry meterRegistry) {
    this.meterRegistry = meterRegistry;
    this.inferenceTimer = Timer.builder("model.inference.duration")
            .description("模型推理耗时")
            .register(meterRegistry);
    this.tokenCounter = Counter.builder("model.generated.tokens")
            .description("生成的token数量")
            .register(meterRegistry);
}

public void recordInference(long durationMs, int tokensGenerated) {
    inferenceTimer.record(durationMs, TimeUnit.MILLISECONDS);
    tokenCounter.increment(tokensGenerated);
}

}
五、 REST API与流式响应

  1. 同步和流式API

java
// ModelController.java
@RestController
@RequestMapping("/api/model")
@Slf4j
public class ModelController {

private final ONNXModelService modelService;
private final ModelConfig config;
private final ModelMetrics metrics;

public ModelController(ONNXModelService modelService, ModelConfig config, ModelMetrics metrics) {
    this.modelService = modelService;
    this.config = config;
    this.metrics = metrics;
}

@PostMapping("/generate")
public ResponseEntity<GenerationResponse> generateText(@RequestBody GenerationRequest request) {
    long startTime = System.currentTimeMillis();

    String generatedText = modelService.generateText(
        request.getPrompt(),
        request.getMaxLength() != null ? request.getMaxLength() : config.getMaxGenerationLength(),
        request.getTemperature() != null ? request.getTemperature() : config.getTemperature()
    );

    long duration = System.currentTimeMillis() - startTime;
    metrics.recordInference(duration, generatedText.length());

    return ResponseEntity.ok(new GenerationResponse(generatedText, duration));
}

@GetMapping(value = "/generate-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public SseEmitter streamGenerate(@RequestParam String prompt,
                                @RequestParam(defaultValue = "512") int maxLength,
                                @RequestParam(defaultValue = "0.7") double temperature) {

    SseEmitter emitter = new SseEmitter(300000L); // 5分钟超时

    CompletableFuture.runAsync(() -> {
        try {
            // 简化版的流式生成实现
            for (int i = 0; i < maxLength; i += 50) { // 分批生成
                String chunk = modelService.generateText(prompt, Math.min(i + 50, maxLength), temperature);
                emitter.send(SseEmitter.event()
                        .data(new StreamChunk(chunk, i))
                        .id(String.valueOf(i)));

                Thread.sleep(100); // 控制流式输出速度
            }
            emitter.complete();
        } catch (Exception e) {
            emitter.completeWithError(e);
        }
    });

    return emitter;
}

// DTO类
@Data
public static class GenerationRequest {
    private String prompt;
    private Integer maxLength;
    private Double temperature;
}

@Data
@AllArgsConstructor
public static class GenerationResponse {
    private String text;
    private long durationMs;
}

@Data
@AllArgsConstructor  
public static class StreamChunk {
    private String text;
    private int progress;
}

}
六、 性能优化与生产实践

  1. 模型量化与压缩

java
// 量化配置(可在模型转换阶段完成)
public class ModelQuantizer {

public static void quantizeModel(String inputModelPath, String outputModelPath) {
    // 使用ONNX Runtime的量化工具
    // 这通常需要在Python环境中执行
    String quantizeScript = """
        import onnxruntime as ort
        from onnxruntime.quantization import quantize_dynamic, QuantType

        quantize_dynamic(
            input_model_path='%s',
            output_model_path='%s', 
            weight_type=QuantType.QUInt8
        )
        """.formatted(inputModelPath, outputModelPath);

    // 执行Python脚本进行量化
    // 量化后可减少模型大小约75%,推理速度提升20-30%
}

}

  1. 批处理推理优化

java
// 批处理推理实现
public class BatchInferenceService {

public List<String> batchGenerate(List<String> prompts, int batchSize) {
    List<String> results = new ArrayList<>();

    for (int i = 0; i < prompts.size(); i += batchSize) {
        List<String> batch = prompts.subList(i, 
            Math.min(i + batchSize, prompts.size()));

        // 动态调整批处理大小
        int actualBatchSize = calculateOptimalBatchSize(batch);
        List<String> batchResults = processBatch(batch, actualBatchSize);
        results.addAll(batchResults);
    }

    return results;
}

private List<String> processBatch(List<String> batch, int batchSize) {
    // 实现批处理逻辑,将多个输入拼接成一个张量
    // 注意:需要处理不同长度的序列(padding)
    return batch.stream()
            .parallel()
            .map(prompt -> modelService.generateText(prompt, 256, 0.7))
            .collect(Collectors.toList());
}

}
七、 部署配置与监控

  1. 生产环境配置

yaml

application-prod.yml

ai:
model:
model-path: "/app/models/phi-3-mini-optimized.onnx"
tokenizer-path: "/app/models/tokenizer"
max-generation-length: 1024
temperature: 0.7
enable-benchmark: true

management:
endpoints:
web:
exposure:
include: health,metrics,info,prometheus
endpoint:
health:
show-details: always
metrics:
export:
prometheus:
enabled: true

JVM优化参数

jvm:
args: >-
-Xmx8g
-Xms4g
-XX:MaxDirectMemorySize=2g
-Donnxruntime.native.performance.tuning=true

  1. 健康检查

java
@Component
public class ModelHealthIndicator implements HealthIndicator {

private final ONNXModelService modelService;

public ModelHealthIndicator(ONNXModelService modelService) {
    this.modelService = modelService;
}

@Override
public Health health() {
    try {
        // 测试推理
        String testResult = modelService.generateText("Test", 10, 0.1);
        if (testResult != null && !testResult.isEmpty()) {
            return Health.up()
                .withDetail("model", "loaded")
                .withDetail("test_output", testResult.substring(0, Math.min(20, testResult.length())))
                .build();
        }
        return Health.down().withDetail("reason", "empty_response").build();
    } catch (Exception e) {
        return Health.down(e).build();
    }
}

}
八、 总结
通过ONNX Runtime实现大模型的本地化部署,Java开发者能够在完全掌控的环境中获得与云端API相媲美的AI能力,同时享受以下优势:

数据安全:敏感数据无需离开本地环境

成本可控:一次性模型部署,无持续API费用

低延迟:消除网络往返延迟,响应更快

完全定制:可根据业务需求微调和优化模型

本文展示的技术栈已在实际生产环境中得到验证,能够支撑中等规模的AI应用需求。随着边缘计算和专用AI芯片的普及,本地化模型部署将成为企业AI应用的主流选择,为Java开发者开辟了新的技术赛道。

目录
相关文章
|
2月前
|
存储 机器学习/深度学习 人工智能
构建AI智能体:三、Prompt提示词工程:几句话让AI秒懂你心
本文深入浅出地讲解Prompt原理及其与大模型的关系,系统介绍Prompt的核心要素、编写原则与应用场景,帮助用户通过精准指令提升AI交互效率,释放大模型潜能。
413 5
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
双 11 电商效率突围:10 款 AI 工具的技术落地与实践指南
2025年双11促销长达38天,电商迎来AI重构关键期。本文剖析10款主流AI工具技术原理,涵盖设计、文案、投放、客服等场景,揭示计算机视觉、自然语言处理等技术如何驱动电商智能化升级,助力企业高效应对大促挑战。
355 1
|
2月前
|
人工智能 测试技术 API
构建AI智能体:二、DeepSeek的Ollama部署FastAPI封装调用
本文介绍如何通过Ollama本地部署DeepSeek大模型,结合FastAPI实现API接口调用。涵盖Ollama安装、路径迁移、模型下载运行及REST API封装全过程,助力快速构建可扩展的AI应用服务。
605 6
|
2月前
|
人工智能 API 开发工具
构建AI智能体:一、初识AI大模型与API调用
本文介绍大模型基础知识及API调用方法,涵盖阿里云百炼平台密钥申请、DashScope SDK使用、Python调用示例(如文本情感分析、图像文字识别),助力开发者快速上手大模型应用开发。
1026 16
构建AI智能体:一、初识AI大模型与API调用
|
2月前
|
云安全 人工智能 安全
Dify平台集成阿里云AI安全护栏,构建AI Runtime安全防线
阿里云 AI 安全护栏加入Dify平台,打造可信赖的 AI
|
2月前
|
SQL 人工智能 关系型数据库
AI Agent的未来之争:任务规划,该由人主导还是AI自主?——阿里云RDS AI助手的最佳实践
AI Agent的规划能力需权衡自主与人工。阿里云RDS AI助手实践表明:开放场景可由大模型自主规划,高频垂直场景则宜采用人工SOP驱动,结合案例库与混合架构,实现稳定、可解释的企业级应用,推动AI从“能聊”走向“能用”。
808 39
AI Agent的未来之争:任务规划,该由人主导还是AI自主?——阿里云RDS AI助手的最佳实践
|
2月前
|
人工智能 缓存 运维
【智造】AI应用实战:6个agent搞定复杂指令和工具膨胀
本文介绍联调造数场景下的AI应用演进:从单Agent模式到多Agent协同的架构升级。针对复杂指令执行不准、响应慢等问题,通过意图识别、工具引擎、推理执行等多Agent分工协作,结合工程化手段提升准确性与效率,并分享了关键设计思路与实践心得。
420 20
【智造】AI应用实战:6个agent搞定复杂指令和工具膨胀
|
2月前
|
机器学习/深度学习 人工智能 JSON
PHP从0到1实现 AI 智能体系统并且训练知识库资料
本文详解如何用PHP从0到1构建AI智能体,涵盖提示词设计、记忆管理、知识库集成与反馈优化四大核心训练维度,结合实战案例与系统架构,助你打造懂业务、会进化的专属AI助手。
213 6
|
2月前
|
人工智能 运维 安全
加速智能体开发:从 Serverless 运行时到 Serverless AI 运行时
在云计算与人工智能深度融合的背景下,Serverless 技术作为云原生架构的集大成者,正加速向 AI 原生架构演进。阿里云函数计算(FC)率先提出并实践“Serverless AI 运行时”概念,通过技术创新与生态联动,为智能体(Agent)开发提供高效、安全、低成本的基础设施支持。本文从技术演进路径、核心能力及未来展望三方面解析 Serverless AI 的突破性价值。

热门文章

最新文章