Solon AI 开发学习16 - generate - 生成模型(图、音、视)

生成模型(GenerateModel) 与 聊天模型(ChatModel)用途区别很大。GenerateModel 只能一次性生成内容,不能对话。比如:

  • 通过文本,生成图片、声音、视频
  • 通过图片,生成视频
  • 等(只要是一次性生成)

补充:GenerateModel 是替代之前的 ImageModel 而新设计的接口,完全兼容 ImageModel 且概念范围更广(旧接口仍可用)。

1、构建生成模型

添加配置

yaml 复制代码
solon.ai.generate:
  demo:
    apiUrl: "https://ai.gitee.com/v1/images/generations" # 使用完整地址(而不是 api_base)
    model: "stable-diffusion-3.5-large-turbo"

构建并测试

java 复制代码
import org.noear.solon.ai.generate.GenerateConfig;
import org.noear.solon.ai.generate.GenerateModel;
import org.noear.solon.ai.generate.GenerateResponse;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;

import java.io.IOException;

@Configuration
public class DemoConfig {
    @Bean
    public GenerateModel build(@Inject("${solon.ai.generate}") GenerateConfig config) {
        return GenerateModel.of(config).build();
    }

    @Bean
    public void test(GenerateModel generateModel) throws IOException {
        //一次性返回
        GenerateResponse resp = generateModel.prompt("一只白色的小花猫").call();

        //打印消息
        System.out.println(resp.getContent().getUrl());
    }
}

2、使用选项

java 复制代码
generateModel.prompt("一只白色的小花猫")
    .options(o -> o.size("1024x1024"))
    .call();
    
generateModel.prompt("一只白色的小花猫")
    .options(o -> {
        o.optionAdd("negative_prompt", "");
        o.optionAdd("sampler_name", "Euler");
        o.optionAdd("scheduler", "Simple");
        o.optionAdd("steps", 25);
        o.optionAdd("width", 512);
        o.optionAdd("height", 768);
        o.optionAdd("batch_size", 1);
        o.optionAdd("cfg_scale", 1);
        o.optionAdd("distilled_cfg_scale", 3.5);
        o.optionAdd("seed", -1);
        o.optionAdd("n_iter", 1);
    })
    .call();    

3、方言适配

生成模型(GenerateModel)同样支持方言适配。框架已内置 OllamaGenerateDialect、DashscopeGenerateDialect、OpenaiGenerateDialect(默认) 三种方言(基本够用),自动支持 Ollama 提供的模型接口、Dashscope 提供的模型接口及 Openai 规范的模型接口。

也可以通过定制,实现更多的模型兼容。方言接口:

java 复制代码
public interface GenerateDialect extends AiModelDialect {
    /**
     * 是否为默认
     */
    default boolean isDefault() {
        return false;
    }

    /**
     * 匹配检测
     *
     * @param config 聊天配置
     */
    boolean matched(GenerateConfig config);

    /**
     * 构建请求数据
     *
     * @param config    聊天配置
     * @param options   聊天选项
     * @param promptStr 提示语文本形态
     * @param promptMap 提示语字典形态
     */
    String buildRequestJson(GenerateConfig config, GenerateOptions options, String promptStr, Map promptMap);

    /**
     * 分析响应数据
     *
     * @param config   聊天配置
     * @param respJson 响应数据
     */
    GenerateResponse parseResponseJson(GenerateConfig config, String respJson);
}

OllamaGenerateDialect 适配参考:

java 复制代码
public class OllamaGenerateDialect extends AbstractGenerateDialect {
    private static OllamaGenerateDialect instance = new OllamaGenerateDialect();

    public static OllamaGenerateDialect getInstance() {
        return instance;
    }

    @Override
    public boolean matched(GenerateConfig config) {
        return "ollama".equals(config.getProvider());
    }

    @Override
    public GenerateResponse parseResponseJson(GenerateConfig config, String respJson) {
        ONode oResp = ONode.load(respJson);

        String model = oResp.get("model").getString();

        if (oResp.contains("error")) {
            return new GenerateResponse(model, new GenerateException(oResp.get("error").getString()), null, null);
        } else {
            List<GenerateContent> data = null;
            if (oResp.contains("response")) {
                //文本模型生成
                String text = oResp.get("response").getString();
                data = Arrays.asList(GenerateContent.builder().text(text).build());
            } else if (oResp.contains("data")) {
                //图像模型生成
                data = oResp.get("data").toObjectList(GenerateContent.class);
            }

            AiUsage usage = null;
            if (oResp.contains("prompt_eval_count")) {
                int prompt_eval_count = oResp.get("prompt_eval_count").getInt();
                usage = new AiUsage(
                        prompt_eval_count,
                        0,
                        prompt_eval_count
                );
            }

            return new GenerateResponse(model, null, data, usage);
        }
    }
}
相关推荐
做萤石二次开发的哈哈4 小时前
连锁门店、园区、交通枢纽的视频如何统一汇集?应用模板的接入与分权管理详解
人工智能·物联网·音视频·二次开发·视频监控·蓝海aiot一站式工作台·萤石云开放平台
老金带你玩AI4 小时前
全程拿着手机,我让dot准备了一场AI分享
人工智能
nvd114 小时前
Flink 批处理驱动的湖仓 AI 财务研报流水线:从双流广播汇聚到 Agent 智能决策与原生 Iceberg 落盘全景实战
大数据·人工智能·flink
snhna4 小时前
向量数据库深度实战:从 HNSW 到 pgvector、Milvus 选型与 RAG 落地
数据库·人工智能·python·postgresql·milvus
架构技术专栏5 小时前
Agent 工具调用:从工具声明到执行反馈
前端·人工智能·后端
点云-激光雷达-Slam-三维牙齿5 小时前
100,000 Records CSV File - India Traffic Accident Analysis Dataset.7z
人工智能·数据集
TechWayfarer5 小时前
精度极限的突破:AI与IPv6如何重塑高精度IP查询
人工智能·网络协议·tcp/ip·transformer
七十二时9565 小时前
视频掉帧怎么用AI补帧
人工智能
可达智灵5 小时前
信创适配|织灵 Coda Loom 2.0 完成银河麒麟服务器操作系统 V10、V11 适配认证
人工智能·可达智灵
别动我齐刘海5 小时前
C++ 工程化学习
java·linux·前端·c++·学习·机器学习·机器人