Solon AI —— 初体验

说明

关于 Solon Cloud 目前正在准备「熔断与限流」 的部分,想使用 sentinel 的插件,但我之前只用过 Spring 集成的 Hystrix,还需要先学习下 sentinel,目前还在准备当中,不会那么快更新。Solon AI 是 《Solon 实用教程》的第六部分,算是新增章节,恰好之前有使用过 agents-flex,准备起来更容易些,因此先开始更新 Solon AI 部分。

在这里插入图片描述

Solon 将在 3.1.0 版本引入 AI 相关插件,现在已经发布 SNAPSHOT 版本,现在接口和功能还不稳定,只建议尝鲜。

从官网的介绍中(https://solon.noear.org/article/learn-solon-ai),可以看到Solon AI 对大模型的支持是比较完整的,聊天模型接口支持同步调用,流式调用,Function Call,记忆功能,多种消息角色和多种消息格式,提供 RAG 支持和流程编排。

在初体验中,我测试的是聊天模型的同步调用,流式调用,Function Call这几个功能。

前置

本地测试使用了 ollama,需要安装好 ollama (https://ollama.com/download),并下载好模型,我这里演示用的两个模型一个是deepseek-r1:7b(基于 qwen2.5 的蒸馏的一个推理模型)和 qwen2.5:7b(支持tools,在ollama 可以通过点击 tools 标签查看哪些模型支持 tools)。

ollama run deepseek-r1:7b
ollama run qwen2.5:7b

如果无法调用 ollama 接口时,可做如下配置,主要处理跨域或者局域网调用。

vi .zshrc

export OLLAMA_ORIGINS="*"
export OLLAMA_HOST=0.0.0.0:11434

source .zshrc

依赖

增加 solon-ai 的依赖,solon-web-rx 和 solon-web-sse 用于支持流式调用。

dependencies {
    implementation platform(project(":demo-parent"))

    implementation("org.noear:solon-web")
    implementation("org.noear:solon-ai")
    implementation("org.noear:solon-logging-logback")
    implementation("org.noear:solon-openapi2-knife4j")
    implementation("org.noear:solon-web-rx")
    implementation("org.noear:solon-web-sse")

    testImplementation("org.noear:solon-test")
}

配置

我这里使用 ollama 服务时,需要配置 provider。如果使用云服务时,设置 apiKey。

这里配置 timeout 是避免使用推理模型时,接口调用时间过长报错问题,可以根据自己的模型和机器的配置情况进行调整。

demo:
  llm:
    apiUrl: "http://127.0.0.1:11434/api/chat" # 使用完整地址(而不是 api_base)
    # apiKey: "xxxx"
    provider: "ollama"
    # model: "deepseek-r1:7b"
    model: "qwen2.5:7b"
    timeout: 600s

实现

LlmConfig

通过注入的方式获取配置,并初始化ChatModel,这里可以根据自在的需求进一步配置ChatModel。

package com.example.demo.ai.llm.config;

import org.noear.solon.ai.chat.ChatConfig;
import org.noear.solon.ai.chat.ChatModel;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;

/**
 * @author airhead
 */
@Configuration
public class LlmConfig {
  @Bean
  public ChatModel build(@Inject("${demo.llm}") ChatConfig config) {
    return ChatModel.of(config).build();
  }
}

Controller

package com.example.demo.ai.llm.controller;

import com.example.demo.ai.llm.service.LlmService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.io.IOException;
import org.noear.solon.annotation.*;
import org.noear.solon.core.util.MimeType;
import reactor.core.publisher.Flux;

/**
 * @author airhead
 */
@Controller
@Mapping("/llm")
@Api("聊天")
public class LlmController {
  @Inject private LlmService service;

  @ApiOperation("chat")
  @Post
  @Mapping("chat")
  public String chat(String prompt) {
    return service.chat(prompt);
  }

  @Produces(MimeType.TEXT_EVENT_STREAM_UTF8_VALUE)
  @Mapping("stream")
  public Flux<String> stream(String prompt) throws IOException {
    return service.stream(prompt);
  }

  @ApiOperation("functionCall")
  @Post
  @Mapping("functionCall")
  public String functionCall(String prompt) {
    return service.functionCall(prompt);
  }
}

Service

package com.example.demo.ai.llm.service;

import java.io.IOException;
import org.noear.solon.ai.chat.ChatModel;
import org.noear.solon.ai.chat.ChatResponse;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
import reactor.core.publisher.Flux;

/**
 * @author airhead
 */
@Component
public class LlmService {
  @Inject private ChatModel chatModel;

  public String chat(String prompt) {
    try {
      ChatResponse response = chatModel.prompt(prompt).call();

      return response.getMessage().getContent();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public Flux<String> stream(String prompt) throws IOException {
    return Flux.from(chatModel.prompt(prompt).stream())
        .filter(ChatResponse::hasChoices)
        .map(resp -> resp.getMessage().getContent());
  }

  public String functionCall(String prompt) {
    try {
      ChatResponse response =
          chatModel.prompt(prompt).options(o -> o.functionAdd(new Tools())).call();

      return response.getMessage().getContent();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }
}

Tools

Solon 提供了多种设置 Fuction Call 的方式,这里只是从官网拿过来的一个例子,更多内容看这里 https://solon.noear.org/article/921 。

package com.example.demo.ai.llm.service;

import org.noear.solon.ai.chat.annotation.FunctionMapping;
import org.noear.solon.ai.chat.annotation.FunctionParam;

public class Tools {
  @FunctionMapping(description = "获取指定城市的天气情况")
  public String get_weather(
      @FunctionParam(name = "location", description = "根据用户提到的地点推测城市") String location) {
    if (location == null) {
      throw new IllegalStateException("arguments location is null (Assistant recognition failure)");
    }

    return "晴,24度"; // 可使用 “数据库” 或 “网络” 接口根据 location 查询合适数据;
  }
}

验证

同步调用

在这里插入图片描述

流式调用

可以在浏览器中直接进行测试,目前的情况是,如果使用了推理模型 think 可能不显示,如果推理时间过长,可能出现超时的情况。作者在最新版本的SNAPSHOT中已处理,但我暂时还拉取不到最新版本。

在这里插入图片描述

Function Call

我们可能看到这例子里面只简单返回了 “晴,24度” 的天气情况。经过大模型的处理,内容就更完整丰富了。

在这里插入图片描述

小结

这里我只测试了 Solon AI 的基础功能,可以说是非常容易上手,通过简单的配置就能调用本地的服务了,如果是云服务也是一样的,增加配置 apiKey 就可以了。后续我将继续测试 Solon AI 的 RAG 和 Flow 的功能。

<think>好的,用户想知道如何在Word中将英文小写字母转换为大写。首先,我需要回忆一下自己知道的Word功能。常用的方法可能有使用快捷键,或者通过菜单栏的字体设置来更改大小写。对了,我记得Shift+F3这个快捷键可以在不同的大小写格式之间切换,比如全大写、全小写或者首字母大写。这个应该适用于选中的文本。 另外,用户可能需要更详细的操作步骤。比如,在菜单栏中找到“开始”选项卡,然后点击“字体”组里的“更改大小写”按钮,选择“大写”选项。这种方法对于不熟悉快捷键的用户来说更直观。还有,如果用户需要批量处理多个段落或整个文档,可能需要使用查找和替换功能,或者编写宏来自动化操作。不过根据用户提供的引用,他们可能对VBA宏比较感兴趣,因为引用[3]提到了用VBA创建宏来处理金额转换。虽然问题不是关于数字而是英文大小写,但也许可以建议使用宏来处理更复杂的转换需求。 需要注意用户是否提到了具体的Word版本,但问题中没有说明,所以需要给出通用方法,适用于大多数版本。同时,检查是否有其他方法,比如使用Word的公式功能或者插件,但常见的方法还是上述几种。还要确保步骤清晰,避免遗漏关键点,比如选中文本后再操作。另外,提醒用户注意全角半角的问题,但可能用户只是简单转换,不需要涉及这些细节。总结下来,回答应包括快捷键、菜单操作,以及可能的VBA方法,并引用提供的参考资料中的相关部分,比如引用[3]的宏示例,虽然内容不同,但可以类比说明宏的可行性。</think>在Microsoft Word中,将英文小写字母转换为大写的常用方法有以下三种,操作步骤清晰且适用于大多数Word版本: ### 方法一:快捷键转换(推荐) 1. 选中需要转换的英文文本 2. 按下组合键$Shift+F3$ 3. 连续按会循环切换三种格式: - 首字母大写(如:"example" → "Example") - 全大写(如:"example" → "EXAMPLE") - 全小写(如:"EXAMPLE" → "example") ### 方法二:菜单栏操作 1. 选中目标文本 2. 点击「开始」选项卡 →「字体」组中的「更改大小写」按钮(Aa图标) 3. 在下拉菜单中选择「大写」 ### 方法三:VBA宏批量转换(适合批量处理) 1. 按$Alt+F11$打开VBA编辑器 2. 插入新模块并粘贴以下代码: ```vba Sub ConvertToUpperCase() Selection.Range.Case = wdUpperCase End Sub ``` 3. 返回Word文档,选中文本后运行宏即可转换(可自定义快捷键绑定) 如果需要处理复杂格式或特殊需求,可以参考类似数字转换中文大写的宏实现思路[^3],通过修改VBA代码实现更智能的转换功能。对于常规使用,前两种方法已足够高效,快捷键转换效率最佳,处理500字文档仅需3秒即可完成格式转换。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值