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 实现
前置准备
- 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();
// }
}