update: remove openai
This commit is contained in:
@@ -37,11 +37,11 @@ export class Ollama extends BaseChat {
|
||||
async listModels(): Promise<{ models: OllamaModel[] }> {
|
||||
const _url = new URL(this.baseURL);
|
||||
const tagsURL = new URL('/api/tags', _url);
|
||||
return this.openai.get(tagsURL.toString());
|
||||
return this.get(tagsURL.toString());
|
||||
}
|
||||
async listRunModels(): Promise<{ models: OllamaModel[] }> {
|
||||
const _url = new URL(this.baseURL);
|
||||
const tagsURL = new URL('/api/ps', _url);
|
||||
return this.openai.get(tagsURL.toString());
|
||||
return this.get(tagsURL.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ export class SiliconFlow extends BaseChat {
|
||||
super({ ...(options as BaseChatOptions), baseURL: baseURL });
|
||||
}
|
||||
async getUsageInfo(): Promise<SiliconFlowUsageResponse> {
|
||||
return this.openai.get('/user/info');
|
||||
return this.get('/user/info');
|
||||
}
|
||||
async chat(messages: OpenAI.Chat.Completions.ChatCompletionMessageParam[], options?: ChatMessageOptions) {
|
||||
const res = await super.chat(messages, options);
|
||||
|
||||
@@ -65,6 +65,7 @@ export class BaseChat implements BaseChatInterface, BaseChatUsageInterface {
|
||||
prompt_tokens: number;
|
||||
total_tokens: number;
|
||||
completion_tokens: number;
|
||||
responseText: string;
|
||||
|
||||
constructor(options: BaseChatOptions) {
|
||||
this.baseURL = options.baseURL;
|
||||
@@ -73,47 +74,121 @@ export class BaseChat implements BaseChatInterface, BaseChatUsageInterface {
|
||||
// @ts-ignore
|
||||
const DEFAULT_IS_BROWSER = getIsBrowser();
|
||||
this.isBrowser = options.isBrowser ?? DEFAULT_IS_BROWSER;
|
||||
this.openai = new OpenAI({
|
||||
apiKey: this.apiKey,
|
||||
baseURL: this.baseURL,
|
||||
dangerouslyAllowBrowser: options?.dangerouslyAllowBrowser ?? this.isBrowser,
|
||||
// this.openai = new OpenAI({
|
||||
// apiKey: this.apiKey,
|
||||
// baseURL: this.baseURL,
|
||||
// dangerouslyAllowBrowser: options?.dangerouslyAllowBrowser ?? this.isBrowser,
|
||||
// });
|
||||
}
|
||||
post(url = '', opts: { headers?: Record<string, string>, data?: any } = {}) {
|
||||
let _url = url.startsWith('http') ? url : this.baseURL + url;
|
||||
return fetch(_url, {
|
||||
method: 'POST',
|
||||
...opts,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${this.apiKey}`,
|
||||
...opts.headers,
|
||||
},
|
||||
body: opts?.data ? JSON.stringify(opts.data) : undefined,
|
||||
});
|
||||
}
|
||||
async get<T = any>(url = '', opts: { headers?: Record<string, string> } = {}): Promise<T> {
|
||||
let _url = url.startsWith('http') ? url : this.baseURL + url;
|
||||
return fetch(_url, {
|
||||
method: 'GET',
|
||||
...opts,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${this.apiKey}`,
|
||||
...opts.headers,
|
||||
},
|
||||
}).then((res) => res.json());
|
||||
}
|
||||
/**
|
||||
* 聊天
|
||||
*/
|
||||
async chat(messages: ChatMessage[], options?: ChatMessageOptions): Promise<ChatMessageComplete> {
|
||||
const createParams: OpenAI.Chat.Completions.ChatCompletionCreateParams = {
|
||||
const requestBody = {
|
||||
model: this.model,
|
||||
messages,
|
||||
...options,
|
||||
stream: false,
|
||||
};
|
||||
const res = (await this.openai.chat.completions.create(createParams)) as ChatMessageComplete;
|
||||
|
||||
const response = await this.post(`${this.baseURL}/chat/completions`, { data: requestBody });
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`Chat API request failed: ${response.status} ${response.statusText} - ${errorText}`);
|
||||
}
|
||||
|
||||
const res = await response.json() as ChatMessageComplete;
|
||||
|
||||
this.prompt_tokens = res.usage?.prompt_tokens ?? 0;
|
||||
this.total_tokens = res.usage?.total_tokens ?? 0;
|
||||
this.completion_tokens = res.usage?.completion_tokens ?? 0;
|
||||
this.responseText = res.choices[0]?.message?.content || '';
|
||||
return res;
|
||||
}
|
||||
async chatStream(messages: ChatMessage[], options?: ChatMessageOptions) {
|
||||
const createParams: OpenAI.Chat.Completions.ChatCompletionCreateParams = {
|
||||
if (options?.response_format) {
|
||||
throw new Error('response_format is not supported in stream mode');
|
||||
}
|
||||
|
||||
const requestBody = {
|
||||
model: this.model,
|
||||
messages,
|
||||
...options,
|
||||
stream: true,
|
||||
};
|
||||
if (createParams.response_format) {
|
||||
throw new Error('response_format is not supported in stream mode');
|
||||
|
||||
const response = await this.post(`${this.baseURL}/chat/completions`, { data: requestBody });
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`Chat Stream API request failed: ${response.status} ${response.statusText} - ${errorText}`);
|
||||
}
|
||||
return this.openai.chat.completions.create(createParams) as unknown as ChatStream;
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
const reader = response.body?.getReader();
|
||||
|
||||
if (!reader) {
|
||||
throw new Error('Response body is not readable');
|
||||
}
|
||||
|
||||
// 创建一个新的 ReadableStream,使用 decoder 解析数据
|
||||
const stream = new ReadableStream({
|
||||
async start(controller) {
|
||||
try {
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) {
|
||||
controller.close();
|
||||
break;
|
||||
}
|
||||
// 检查 value 类型,如果是 Uint8Array 才解码,否则直接使用
|
||||
if (typeof value === 'string') {
|
||||
controller.enqueue(value);
|
||||
} else if (value instanceof Uint8Array) {
|
||||
const text = decoder.decode(value, { stream: true });
|
||||
controller.enqueue(text);
|
||||
} else {
|
||||
controller.enqueue(value);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
controller.error(error);
|
||||
}
|
||||
},
|
||||
cancel() {
|
||||
reader.releaseLock();
|
||||
}
|
||||
});
|
||||
|
||||
return stream as unknown as ChatStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试
|
||||
*/
|
||||
test() {
|
||||
return this.chat([{ role: 'user', content: 'Hello, world!' }]);
|
||||
}
|
||||
/**
|
||||
* 获取聊天使用情况
|
||||
* @returns
|
||||
@@ -125,6 +200,7 @@ export class BaseChat implements BaseChatInterface, BaseChatUsageInterface {
|
||||
completion_tokens: this.completion_tokens,
|
||||
};
|
||||
}
|
||||
|
||||
getHeaders(headers?: Record<string, string>) {
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -139,12 +215,23 @@ export class BaseChat implements BaseChatInterface, BaseChatUsageInterface {
|
||||
*/
|
||||
async generateEmbeddingCore(text: string | string[], options?: EmbeddingMessage): Promise<EmbeddingMessageComplete> {
|
||||
const embeddingModel = options?.model || this.model;
|
||||
const res = await this.openai.embeddings.create({
|
||||
|
||||
const requestBody = {
|
||||
model: embeddingModel,
|
||||
input: text,
|
||||
encoding_format: 'float',
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
const response = await this.post(`${this.baseURL}/embeddings`, { data: requestBody });
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
throw new Error(`Embedding API request failed: ${response.status} ${response.statusText} - ${errorText}`);
|
||||
}
|
||||
|
||||
const res = await response.json() as EmbeddingMessageComplete;
|
||||
|
||||
this.prompt_tokens += res.usage.prompt_tokens;
|
||||
this.total_tokens += res.usage.total_tokens;
|
||||
return res;
|
||||
|
||||
@@ -2,17 +2,6 @@ import { ChatStream } from './type.ts';
|
||||
|
||||
// export type { BaseChat, BaseChatOptions } from './chat.ts';
|
||||
export * from './chat.ts'
|
||||
// export {
|
||||
// ChatMessage,
|
||||
// ChatMessageOptions, //
|
||||
// ChatMessageComplete,
|
||||
// ChatMessageStream,
|
||||
// BaseChatInterface,
|
||||
// BaseChatUsageInterface,
|
||||
// ChatStream,
|
||||
// EmbeddingMessage,
|
||||
// EmbeddingMessageComplete,
|
||||
// } from './type.ts';
|
||||
export * from './type.ts'
|
||||
/**
|
||||
* for await (const chunk of chatStream) {
|
||||
|
||||
@@ -7,8 +7,8 @@ export class SiliconFlowKnowledge extends KnowledgeBase {
|
||||
}
|
||||
|
||||
async rerank(data: RerankOptions) {
|
||||
return this.openai.post('/rerank', {
|
||||
body: data,
|
||||
return this.post('/rerank', {
|
||||
data: data,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,16 +11,49 @@ const ai = new BailianProvider({
|
||||
})
|
||||
|
||||
|
||||
const res = await ai.chat([
|
||||
// const res = await ai.chat([
|
||||
|
||||
{
|
||||
role: 'user',
|
||||
content: `1+1等于多少?`
|
||||
},
|
||||
|
||||
],
|
||||
)
|
||||
console.log('AI Response:', res);
|
||||
const content = res.choices[0].message?.content || ''
|
||||
// {
|
||||
// role: 'user',
|
||||
// content: `1+1等于多少?`
|
||||
// },
|
||||
|
||||
console.log(util.inspect(res, { depth: null }))
|
||||
// ],
|
||||
// )
|
||||
// // console.log('AI Response:', res);
|
||||
// const content = res.choices[0].message?.content || ''
|
||||
|
||||
// console.log(util.inspect(res, { depth: null }))
|
||||
|
||||
// console.log('responseText', ai.responseText)
|
||||
|
||||
|
||||
// const res = await ai.chatStream([
|
||||
|
||||
// {
|
||||
// role: 'user',
|
||||
// content: `1+1等于多少?`
|
||||
// },
|
||||
|
||||
// ],
|
||||
// )
|
||||
// // console.log('AI Response:', res);
|
||||
// export const readStream = async (chatStream) => {
|
||||
// let buffer = '';
|
||||
// for await (const chunk of chatStream) {
|
||||
// // chunk 已经是解码后的字符串,直接拼接即可
|
||||
// buffer += chunk;
|
||||
// }
|
||||
// console.log('AI Response:', buffer);
|
||||
// };
|
||||
|
||||
// await readStream(res);
|
||||
|
||||
const embe = await ai.generateEmbeddingCore([
|
||||
'你好,世界!',
|
||||
'Hello, world!',
|
||||
], {
|
||||
model: 'text-embedding-v4'
|
||||
});
|
||||
|
||||
console.log('Embedding Response:', util.inspect(embe, { depth: null }));
|
||||
Reference in New Issue
Block a user