feat: 支持查询天气

This commit is contained in:
arvinxx
2023-07-23 15:53:34 +08:00
parent ea9e8de26c
commit 34bf285738
4 changed files with 81 additions and 4 deletions

View File

@@ -1,8 +1,13 @@
import { OpenAIStream, StreamingTextResponse } from 'ai';
import { Configuration, OpenAIApi } from 'openai-edge';
import { ChatCompletionFunctions, ChatCompletionRequestMessage } from 'openai-edge/types/api';
import { OpenAIStreamPayload } from '@/types/openai';
import { plugins } from './plugins';
export const runtime = 'edge';
const isDev = process.env.NODE_ENV === 'development';
const OPENAI_PROXY_URL = process.env.OPENAI_PROXY_URL;
@@ -13,19 +18,38 @@ const config = new Configuration({
const openai = new OpenAIApi(config, isDev && OPENAI_PROXY_URL ? OPENAI_PROXY_URL : undefined);
export const runtime = 'edge';
const functions: ChatCompletionFunctions[] = plugins.map((f) => f.schema);
export default async function handler(req: Request) {
// Extract the `messages` from the body of the request
const { messages, ...params } = (await req.json()) as OpenAIStreamPayload;
console.log(params);
const formatMessages = messages.map((m) => ({ content: m.content, role: m.role }));
const response = await openai.createChatCompletion({
functions,
messages: formatMessages,
stream: true,
...params,
messages: messages.map((m) => ({ content: m.content, role: m.role })),
});
const stream = OpenAIStream(response);
const stream = OpenAIStream(response, {
experimental_onFunctionCall: async ({ name, arguments: args }, createFunctionCallMessages) => {
const func = plugins.find((f) => f.name === name);
if (func) {
const result = await func.runner(args as any);
const newMessages = createFunctionCallMessages(result) as ChatCompletionRequestMessage[];
return openai.createChatCompletion({
functions,
messages: [...formatMessages, ...newMessages],
stream: true,
...params,
});
}
},
});
return new StreamingTextResponse(stream);
}

View File

@@ -0,0 +1,3 @@
import getWeather from './weather';
export const plugins = [getWeather];

View File

@@ -0,0 +1,20 @@
import runner from './runner';
const schema = {
description: '获取当前天气情况',
name: 'fetchWeather',
parameters: {
properties: {
city: {
description: '城市名称',
type: 'string',
},
},
required: ['city'],
type: 'object',
},
};
const getWeather = { name: 'fetchWeather', runner, schema };
export default getWeather;

View File

@@ -0,0 +1,30 @@
const weatherBaseURL = 'https://restapi.amap.com/v3/weather/weatherInfo';
const citySearchURL = 'https://restapi.amap.com/v3/config/district';
const KEY = process.env.GAODE_WEATHER_KEY;
interface WeatherParams {
city: string;
extensions?: 'base' | 'all';
}
const fetchCityCode = async (keywords: string): Promise<string> => {
const URL = `${citySearchURL}?keywords=${keywords}&subdistrict=0&extensions=base&key=${KEY}`;
const res = await fetch(URL);
const data = await res.json();
return data.districts[0].adcode;
};
const fetchWeather = async ({ city, extensions = 'all' }: WeatherParams) => {
const cityCode = await fetchCityCode(city);
const URL = `${weatherBaseURL}?city=${cityCode}&extensions=${extensions}&key=${KEY}`;
const res = await fetch(URL);
return await res.json();
};
export default fetchWeather;