目录
偷懒的编写一个API
如何让ChatGPT理解我们都在聊什么
付费和一些注意事项
Create chat completion
最近ChatGPT这么火,那必须来凑个热闹啊。
申请账户我就不多说了,懂得都懂。
从ChatGPT的Chat演示看,他需要一个持续的长链接,所以我使用SignalR+JWT来走这个场景。
具体SignalR+JWT怎么做,就不多介绍了。
因为对接ChatGPT没有过类似经验,肯定优先看NuGet的库里面有没有开发好的内容。
首次尝试:
我第一次使用的是这个包,在实际尝试的时候,我没有找到对应的文档,并且他返回的内容要等全部内容返回后才出现,这个时间很长,有可能是因为我没有找到逐渐输出的这种方式。所以放弃没有继续使用。
第二次尝试:
使用了OkGoDoIt 做的这个SDK,这个SDK调用起来很简单,只需要:
public class ChatGptHub : Hub
{
private readonly string sessionToken = "";
public async Task Conversation(string msg)
{
try
{
OpenAIAPI api = new(sessionToken);
await foreach (var token in api.Completions.StreamCompletionEnumerableAsync(new CompletionRequest(msg,
model: Model.DavinciText,
max_tokens: 512,
temperature: 0.9,
top_p: 1,
presencePenalty: 0.6,
frequencyPenalty: 0)))
{
await Clients.Caller.SendAsync("Reply", $"{token}");
}
}
catch(Exception ex)
{
await Clients.Caller.SendAsync("Reply", "服务器有点忙, 稍后再试试吧~");
}
}
}
就可以使用了,它会通过Reply返回每一个字给到前端。
msg: 是我传递的带有上下文的信息,具体可以继续看下去;
max_tokens:是返回最多多少个字,一个英文字母是4个字节
temperature:是温度,他的值越高,AI越有感情。
top_p:我也没太明白是干嘛的,有兴趣你可以直接问ChatGPT
presencePenalty和frequencyPenalty:一种惩罚,如果给这个值设置超过0,会对模型返回结果进行惩罚。例如,如果希望减少生成语句中任何重复的词语或短语,则可以加大 "presencePenalty";如果希望减少生成语句中出现次数较多的重复词语或短语,则可以加大 "frequencyPenalty"。我在实际测试中没有发现特别大的变化,可能是因为中文的缘故。
它需要知道上下文信息,我们需要自己制造上下文给到CompletionRequest 的第一个参数。
我的做法是在界面中设置一个隐藏的textarea,然后给角色赋值,就像playground中一样:在上图的负载中可以看到,我问他天空的颜色,然后问他为什么会是其他颜色,这里如果按照文字逐行理解,他应该是无法分析出“为什么会有其他颜色?”这种问题。
那么传递数据的时候,我也要制造出这样的内容:
AI:我叫小娜
Human:你好啊。
AI:很高兴认识你,请问我有什么可以帮你?
Human:你叫什么?
AI:我叫小娜
Human:xxxxxxxx
否则他会随便说一个名字,是不是很尴尬?可以让这个textarea在初始化的时候直接写一个: (记得换行)
AI: 你好,我叫小娜,很高兴为您服务。
Human:
这样,你下次下发到接口时,接口就知道他的名字叫“小娜”了。
上述方法同样有助于让AI知道你在说中文,带上上下文,他回答英文的概率变小了。
对接还是很简单的,就是这服务器反应速度略慢。
经过了一段时间的学些,此处有一些补充:
1. ChatGPT API的收费标准:在chat.openai.com中对话的Chat 是达芬奇(Davinci) 002 ,而在API中只能使用达芬奇003或者下图的这些机器人模型。
0.02美元一千个Token,那Token怎么理解呢?如果他说英文,一般一个英文词是一个Token,例如:What's your name. 是4个token,具体是多少个,可以去看一下官方的token计算器。中文就比较贵了一个字是1-2个Token。
2. Request:请求的收费标准是这样的:
Completions requests are billed based on the number of tokens sent in your prompt plus the number of tokens in the completion(s) returned by the API.
The best_of
and n
parameters may also impact costs. Because these parameters generate multiple completions per prompt, they act as multipliers on the number of tokens returned.
Your request may use up to num_tokens(prompt) + max_tokens * max(n, best_of)
tokens, which will be billed at the per-engine rates outlined at the top of this page.
In the simplest case, if your prompt contains 10 tokens and you request a single 90 token completion from the davinci engine, your request will use 100 tokens and will cost $0.002.
You can limit costs by reducing prompt length or maximum response length, limiting usage of best_of
/n
, adding appropriate stop sequences, or using engines with lower per-token costs.
够贵的啊,他说如果我在prompt中传10个字,API返回了90个字,那就收100个token的费用。所以如果有必要,请谨慎使用上下文功能。
3. 这是一个命题作文:
如何让ChatGPT有一些个性来回复内容呢?下方是一个官方示例:
Marv is a chatbot that reluctantly answers questions with sarcastic responses:
You: How many pounds are in a kilogram?
Marv: This again? There are 2.2 pounds in a kilogram. Please make a note of this.
You: What does HTML stand for?
Marv: Was Google too busy? Hypertext Markup Language. The T is for try to ask better questions in the future.
You: When did the first airplane fly?
Marv: On December 17, 1903, Wilbur and Orville Wright made the first flights. I wish they’d come and take me away.
You: What is the meaning of life?
Marv: I’m not sure. I’ll ask my friend Google.
You: Why is the sky blue?
马维就会不耐烦的回答问题,同样你可以说:
AI是一个聊天机器人,她只能用中文回答Human提出的问题。
/* 以下是你说的内容 可以通过接口传递 */
Human: 你好
/* 以下是GPT回复的内容 */
AI: 你好,很高兴认识你.
说不明白, 直接上代码: 这里需要stopSequences ,它在回复Token的时候会不去回复指定的string[]内容. 可以减少Token输出量.
try
{
string basePormpt = $"AI是一个聊天机器人,她只能用中文回答Human提出的问题。\n\nHuman:{pormpt}\nAI:";
OpenAIAPI api = new(sessionToken);
await foreach (var token in api.Completions.StreamCompletionEnumerableAsync(new CompletionRequest(basePormpt,
model: Model.DavinciText,
max_tokens: 150,
temperature: 0.5,
top_p: 1,
presencePenalty: 0.6,
frequencyPenalty: 0, stopSequences:new string[] {"Human:","AI:" })))
{
await Clients.Caller.SendAsync("Reply", $"{token}");
await Task.Delay(200);
}
}
catch (Exception ex)
{
await Clients.Caller.SendAsync("Reply", "服务器有点忙, 我正在重新尝试请求~");
DebugLog.WriteLine($"ChatGptHub:错误内容: {ex}");
}
继续更新,在3月1日,Openai公布了GPT-3.5-turbo模型,这个模型的主要功能就是进行chat,并公布了新的api:对话完成。
这个接口收费更低一些,0.002美元1K个token,比达芬奇003便宜了10倍。但是这个模型只能用在chat中,不可以用来做文本完成。
根据我这段时间的分析,我认为之前的AI对话,是模型在完成后续的内容(文本完成),它并不像chat.openai.com那样是在直接对话。
新的这个api我看这个OkGoDoIt 还没有去做,在pull request中,有一位叫megalon的人做好了,正在提交测试,我决定等等。但是在等待之前,我可以通过postman,来进行一下初步的测试。以下是我的测试结果:
可选参数我都没有写,需要的朋友可以自行添加,详见对话完成 API说明
{
"model": "gpt-3.5-turbo",
"stream":true,
"messages": [{"role": "user", "content": "天空是什么颜色的?"}]
}
open ai streaming
这是一个使用streaming方式获得OpenAI Chat API的返回内容, 这个明显首次响应会很快, 他毕竟是一个字一个字的返回给我们。
open ai not streaming
这是不使用流,等待所有内容组织好之后返回给我们的,他的缺点就是返回速度很慢,但优点是,你可以知道他是一句话,可以使用TTS接口,将他读出来。
您的IP:18.189.188.157,2025-05-04 00:02:20,Processed in 5.27216 second(s).