概要
本文将简单介绍如何使用NestJS框架接入DeepSeek开放API,帮助开发者快速实现API集成。文章将从NestJS项目初始化开始,逐步讲解如何申请开放apikey、调用SDK、实现普通接口请求以及SSE方式实现,另外扩展如何调用本地的Ollama模型。通过本文,读者将掌握如何利用NestJS接入deepseek的开放API。本文只是分享一下我的思路,只提供一个MVP代码示例,更多功能自行摸索尝试,有机会后续也会继续分享。如有错误之处,欢迎各位大佬评论区或私信讨论~
效果预览
一. 准备工作
首先,我们先在本地搭建一个nestjs项目
bash
npm i -g @nestjs/cli
nest new [project name]
详细过程不再展开
第二步:我们去deepseek开放平台注册账号,并申请apikey,一定要保存好,他这里只展示这一次,忘记了就需要重新创建了
这里需要实名认证,并充值,deepseek的开放接口定价还是挺便宜的
模型&价格细节
以上都完成申请完成后可以在这里管理你的apikey
恭喜,到这里你已经完成了全部的前置准备工作
二、代码编写
创建deepseek模块,可以随意起名
bash
nest g res deepseek
// 安装`openai`模块
pnpm add openai
目录结构如下
编写接口,我们实现两种方式:
ts
// deepseek.controller.ts
import { Body, Controller, HttpCode, Post, Query, Sse } from '@nestjs/common';
import { DeepseekService } from './deepseek.service';
@Controller('deepseek')
export class DeepseekController {
constructor(private readonly deepseekService: DeepseekService) {}
@Post()
@HttpCode(200)
// 定义一个名为 getHello 的方法,该方法接收一个名为 msg 的字符串参数
getHello(@Body('msg') msg: string) {
// 调用 deepseekService 的 generate 方法,并将 msg 作为参数传递给它
// generate 方法会根据传入的 msg 生成一些内容,并将其作为返回值返回
return this.deepseekService.generate(msg);
}
@Sse()
// 定义一个名为 sse 的方法,该方法接收一个查询参数 msg,并返回一个结果
sse(@Query('msg') msg: string) {
// 调用 deepseekService 服务的 sse 方法,并将查询参数 msg 作为参数传递
// 然后将 deepseekService.sse 方法的返回值作为当前方法的返回值
return this.deepseekService.sse(msg);
}
}
ts
// deepseek.service.ts
import { Injectable } from '@nestjs/common';
import OpenAI from 'openai';
import { from, map } from 'rxjs';
const openai = new OpenAI({
baseURL: 'https://api.deepseek.com',
apiKey: 'sk-xxxxxxxxx',
});
@Injectable()
export class DeepseekService {
// 定义一个异步函数 generate,接收一个字符串参数 msg,默认值为 '你是谁?'
async generate(msg: string = '你是谁?') {
// 调用 openai 的 chat.completions.create 方法,生成聊天回复
// 传入的参数是一个对象,包含 messages、model 和 stream 三个属性
// messages 是一个数组,包含一个对象,表示用户的提问,role 为 'user',content 为传入的 msg 参数
// model 指定使用的模型为 'deepseek-chat'
// stream 设置为 false,表示不使用流式响应
const completions = await openai.chat.completions.create({
messages: [{ role: 'user', content: msg }],
model: 'deepseek-chat',
stream: false,
});
// 打印生成的回复对象
console.log('completions', completions);
return completions.choices[0].message?.content;
}
// 定义一个异步函数 sse,接收一个字符串参数 msg,默认值为 '你是谁?'
async sse(msg: string = '你是谁?') {
// 使用 openai 的 chat.completions.create 方法创建一个聊天完成请求
// 请求参数包括消息数组(包含用户角色和内容),使用的模型,以及是否开启流式响应
const response = await openai.chat.completions.create({
messages: [{ role: 'user', content: msg }], // 消息数组,包含一个用户角色和内容
model: 'deepseek-chat', // 使用的模型名称
stream: true, // 开启流式响应
});
// 初始化一个空字符串数组 res,用于存储每一部分的响应内容
const res: string[] = [];
// 返回一个 Observable 对象,通过 from 操作符将 response 转换为可观察对象
// 然后使用 pipe 操作符进行一系列操作
return from(response).pipe(
// 使用 map 操作符对每一部分响应进行处理
map((part) => {
// 将当前部分的 delta 内容(如果存在)添加到 res 数组中,否则添加空字符串
res.push(part.choices[0].delta?.content || '');
// 将 res 数组中的所有内容连接成一个字符串并返回
return res.join('');
}),
);
}
}
调用方式:
- 使用post请求调用:调用nestjs服务,我的是启动在
3333
端口,并且全局添加了/api
前缀
- 使用SSE,这个需要特别说明一下,直接使用
get
请求localhost:3333/api/deepseek?msg=你是谁?
地址,但是这样子直接发起请求是不行的,还需要设置一下请求头Content-Type
为text/event-stream
,这时候就可以了,效果就是文章开头的效果预览
至此,我们使用nestjs调用deepseek开放API的功能就已经实现了
三、调用本地的Ollama本地大语言模型
其实这种方式只适合自己本地玩玩,本机部署的大模型想让公网能够访问,需要配置内网穿透,具体这里不再展开,感兴趣的自行了解
下面说说如何调用本地的大模型,直接上代码
bash
// 安装SDK
pnpm add ollama
至于如何本地部署本地大模型,不再赘述,最近很多文章都有讲
ts
// ollama.service.ts
import { Injectable } from '@nestjs/common';
import { Message, Ollama } from 'ollama';
import { from, map } from 'rxjs';
const ollama = new Ollama({ host: 'http://127.0.0.1:11434' });
@Injectable()
export class OllamaService {
// 定义一个异步函数chat,用于与聊天模型进行对话
async chat(prompt: string = 'who are you?') {
// 初始化消息数组,默认用户输入为'who are you?'
const messages: Message[] = [{ role: 'user', content: prompt }];
// 调用ollama的chat方法,传入模型名称、消息数组和流模式
const response = await ollama.chat({
model: 'deepseek-r1:1.5b', // 指定使用的模型名称
messages, // 传入的消息数组
stream: true, // 启用流模式,以便实时获取响应
});
// 初始化一个空数组,用于存储每部分的消息内容
const res: string[] = [];
// 返回一个Observable对象,通过from操作符将response转换为Observable
return from(response).pipe(
// 使用map操作符处理每一部分的数据
map((part) => {
res.push(part.message.content); // 将每部分的消息内容添加到res数组中
return res.join(''); // 将res数组中的所有消息内容连接成一个字符串并返回
}),
);
}
}
ts
// ollama.controller.ts
import { Controller, Query, Sse } from '@nestjs/common';
import { OllamaService } from './ollama.service';
@Controller('ollama')
export class OllamaController {
constructor(private readonly ollamaService: OllamaService) {}
@Sse('chat')
// 定义一个名为chat的方法,该方法接收一个Query参数
chat(@Query() query: Record<string, any>) {
// 在控制台打印出'ollama controller'和传入的query参数
console.log('ollama controller', query);
// 调用this.ollamaService的chat方法,传入query.msg的值,如果query.msg不存在则传入undefined
return this.ollamaService.chat(query.msg || undefined);
}
}
效果预览
四. 总结
- 本文主要介绍了如何在本地通过nestjs启动一个服务,并使用
openai
SDK调用deepseek
开放API,以及使用ollama
SDK调用本地大语言模型 - 本文没有深入介绍nestjs相关的其他细节内容,也未扩展讲本地部署大模型的步骤,更多细节及更多完整功能的实现欢迎大家讨论
NOTE:文中的代码注释均由
VsCode CodeGeeX插件生成
,这个时代,谁还自己写注释 /dog 🐶