用java和JavaScript写同一个Ai后端小项目,感觉java不香了😥

4 阅读3分钟

JavaScript 在后端的应用主要基于 Node.js。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,它让 JavaScript 可以脱离浏览器,在服务器端运行。这意味着开发者可以使用熟悉的 JavaScript 语言来构建服务器端应用程序,也就是说优雅的javaScript又换了一个舞台来表演!!!

需求

通过调用 openai 来分析图中的信息

简单设计

声明 : 我的 demo 只是为了跑通 demo🤡 , 如果真的要设计一个后端系统, 有诸多地方需要考虑

比如 :

  • 攻击者绕过前端 , 直接向后端高频率请求 openai 的 api , 此时就需要采用中间件来拦截请求,做出一定的处理。
  • api 的 token 快用完了 , 需要做出预警 ,比如可以在后端编写逻辑,记录使用的次数。
  • 假设 openai 返回的数据不是准确的 , 后端如何通过逻辑去调整。
  • 异步还是同步?
  • ......

悄悄告诉你 : 你可以通过中转网站的形式调用api , 如果有钱可以无需中转 , 但可能需要配置代理 , 你需要使用点魔法🤡

JS 实现

前置准备

 npm init -y  初始化后端项目
 npm  i  openai 引入openai依赖
 npm  -g openai (全局安装 , 不推荐)


 建议使用pnpm
 npm i  -g pnpm  ( pnpm是一个快速、节省磁盘空间的npm包管理器,它通过使用符号链接来避免重复下载相同的包 )
 无法下载或下载过慢 , 使用淘宝镜像
 npm config set registry [https://registry.npmmirror.com](https://registry.npmmirror.com) (配置国内镜像源)

实现

优雅实现调用 api


import OpenAI from "openai";
//实例化openai 客户端 
const client = new OpenAI({
    apiKey: 'xxx',
    baseURL: 'xxx' // 转发 
})

const main = async () => {
    // openai 的调用是异步的 
    // await 等会儿
    // chat 聊天的方式调用
    // completions 完成问答
    // create 创建
    const response = await client.chat.completions.create({
        model: 'gpt-4o',
        messages: [{
            role: 'user',
            content: [{
                    type: 'text',
                    'text': '请描述以下图片的内容'
                },
                {
                    type: 'image_url',
                    "image_url": {
                        "url": "https://img.huxiucdn.com/img/minitopic/202406/25/084826659075.jpg?imageView2/1/w/512/h/512/|imageMogr2/strip/interlace/1/quality/85"
                    }
                }
            ]
        }],
        max_tokens: 300 
    })
    console.log(response.choices[0].message.content)
}

main()

再看看 java 实现, 他一如既往的笨重

如果在“优雅方面”, js 还是可以上号的!

java 实现

前置准备

  1. jdk17

2 springboot3

可参考官方文档 springAi

封装了很多大模型

Spring AI - Spring 框架 (springframework.org.cn)

实现

创建完后会发现加入了依赖

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.ai</groupId>
      <artifactId>spring-ai-bom</artifactId>
      <version>1.0.0-SNAPSHOT</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>


  <dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>

  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
  </dependency>

</dependencies>

设置key

ganzhibin:
  # 中转(自行配置)
  aicore:
    key: ${OPEN_AI_KEY}
    url: ${OPEN_AI_URL}

spring:
  ai:
    openai:
      api-key: ${ganzhibin.aicore.key}
      base-url: ${ganzhibin.aicore.url}

示例代码


@RestController
@RequestMapping("/ai")
@Slf4j
@RequiredArgsConstructor
class AiController {

    //智能对话客户端

    //private final ChatClient chatClient;

    private final ChatModel chatModel;

    // private final OpenAiImageModel openaiImageModel;

    // private final OpenAiAudioSpeechModel openAiAudioSpeechModel;

    // private  final OpenAiAudioTranscriptionModel openAiAudioTranscriptionModel;


    //#####################################################chatModel多模态####################################################################################
    @GetMapping("/multimodal/readImage")

    String multiModal(@RequestParam(value = "message", defaultValue = "从这张图片你看到了什么?") String message) {

        var imageResource = new ClassPathResource("/test.png");

        var userMessage = new UserMessage(
                message,
                new Media(MimeTypeUtils.IMAGE_PNG, imageResource));

        ChatResponse response = chatModel.call(new Prompt(userMessage,
                OpenAiChatOptions.builder().withModel(OpenAiApi.ChatModel.GPT_4_O.getValue()).build()));

        return response.getResult().getOutput().getContent();
    }

    // //#####################################################Function-call########################################################################################
    // @GetMapping("/functionCall/queryWeather")

    // String functionCall() {
    //     UserMessage userMessage = new UserMessage("What's the weather like in San Francisco, Tokyo, and Paris?");
    //     ChatResponse response = chatModel.call(new Prompt(userMessage,
    //             OpenAiChatOptions.builder().withFunction("currentWeather").build())); // Enable the function
    //     return response.getResult().getOutput().getContent();
    // }
}