抖音粉丝群1
『7x24小时有问必答』

AI浪潮下的计算机行业——从业者现状与未来展望
↓推荐关注↓
前言
最近这个ChatGPT很火啊,看了B站上很多视频,自己非常手痒,高低自己得整一个啊,但是让我很难受的是,翻遍了github前十页,竟然没有一个C#的ChatGPT项目,我好难受啊!那能怎么办?自己搞一个吧。
但是,等等,现在的ChatGPT项目基本都是网页逆向获取几个token,我不会啊,我都不知道哪些cookie是重要的,那我只能找一个其它语言的ChatGPT API项目,自己造(翻译)一个C#的ChatGPT API库了。
ChatGPT是什么?
先了解GTP,摘自官网的一段话“A set of models that can understand and generate natural language”,其实,就是一个自然语言处理的模型。所以ChatGPT顾名思义就是基于GPT3的一个聊天AI。
但是想让他做苦力帮忙写代码的话所需要的其实不是这个模型,而是Codex这个模型,按照官网所说“Most capable Codex model. Particularly good at translating natural language to code. In addition to completing code, also supports inserting completions within code.”。真的是碉堡了!

准备

第一步:注册OpenAI账号
因为对大陆以及中国香港地区不开放,所以我们需要小小的科学一下。

来一个我就是参照着申请账号的园子的文章: https://www.cnblogs.com/chatgpt/p/how-to-register-chatgpt-in-china.html 当然手机那里可以淘宝找,几块钱就能帮忙注册手机,账号里面默认还有18美元余额。

注意点:如果搭建了科学还是提示不对你的国家提供服务的话,尝试清空浏览器缓存或者打开浏览器的无痕窗口。
Chrome默认在右上角三个点打开就能找到“打开新的无痕式窗口”。
万事具备,直接撸代码
1、网页获取所需token和cookie
我们需要三个东西:UserAgent,CfClearance,Session_token

我们需要先打开ChatGPT官方网站:https://chat.openai.com/chat 然后按下F12打开浏览器的开发者模式 UserAgent在网络里(只需要复制UserAgent:后面的值):

CfClearance和Session_token在应用程序->cookie里面

2、创建一个session用来表示一个会话

public OpenAISession(string session_token,string cfClearance,string userAgent)

{

    Session_token = session_token;

    CfClearance = cfClearance;

    UserAgent = userAgent;

    Headers = new Dictionary<stringstring>();

    Cookies = new Dictionary<stringstring>();

    Proxies = new Dictionary<stringstring>();

}

Session可以刷新自己的AccessToken和Session_token
public async Task RefreshSessionAsync()

{

    if (string.IsNullOrEmpty(Session_token))

    {

        throw new Exception("No tokens provided");

    }

    // Set cookies

    Cookies.Put("__Secure-next-auth.session-token", Session_token);

    Cookies.Put("cf_clearance", CfClearance);

    string cookiesString = GetCookiesString();

    Dictionary<stringstring> map = new Dictionary<stringstring>();

    Headers.Put("User-Agent", UserAgent);

    Headers.Put("cookie", cookiesString);

    Headers.Put("Cookie", cookiesString);

    var response = await GetAsync("https://chat.openai.com/api/auth/session");

    if (!response.IsSuccessStatusCode)

    {

        Console.WriteLine("err code: " + response.StatusCode);

        Console.WriteLine("cf_clearance: " + CfClearance);

        Console.WriteLine("token: " + Session_token);

        Console.WriteLine("userAgent: " + UserAgent);

        Console.WriteLine("请检查以上参数是否正确,是否过期。");

        throw new Exception("无法获取token!请重试");

    }

    try

    {

        string name = "__Secure-next-auth.session-token=";

        var cookies = response.Headers.GetValues("Set-Cookie");

        var stoken = cookies.FirstOrDefault(x => x.StartsWith(name));

        Session_token = stoken == null ? Session_token : stoken.Substring(name.Length, stoken.IndexOf(";") - name.Length);

        Cookies.Put("__Secure-next-auth.session-token", Session_token);

        var result = await response.Content.ReadAsStringAsync();

        AccessToken = JsonSerializer.Deserialize(result, _jsonSerializerOptions)?.AccessToken;

        RefreshHeaders();

    }

    catch (Exception ex)

    {

        Console.WriteLine($"Error {nameof(RefreshSessionAsync)}:{ex}");

        throw new Exception($"Error {nameof(RefreshSessionAsync)}", ex);

    }

}

获取到的最新的AccessToken更新到header里,Session_token更新到cookie里
private void RefreshHeaders()

{

    Headers.Put("Host""chat.openai.com");

    Headers.Put("Accept""text/event-stream");

    Headers.Put("Authorization"$"Bearer {AccessToken}");

    Headers.Put("User-Agent", UserAgent);

    Headers.Put("X-Openai-Assistant-App-Id"string.Empty);

    Headers.Put("Connection""close");

    Headers.Put("Accept-Language""en-US,en;q=0.9");

    Headers.Put("Referer""https://chat.openai.com/chat");

}

string name = "__Secure-next-auth.session-token=";

var cookies = response.Headers.GetValues("Set-Cookie");

var stoken = cookies.FirstOrDefault(x => x.StartsWith(name));

Session_token = stoken == null ? Session_token : stoken.Substring(name.Length, stoken.IndexOf(";") - name.Length);

Cookies.Put("__Secure-next-auth.session-token", Session_token);

3、创建机器人绑定一个会话

public Chatbot(OpenAISession openAISession)

{

    OpenAISession = openAISession;

    ResetConversation();

}

/// 

/// 重置Conversation,开启一个新的会话

/// 

public void ResetConversation() 

{

    _conversationId = null;

    _parentMessageId = Guid.NewGuid().ToString();

}

如何保持上下文聊天以及多用户隔离?
上下文聊天已经内置,会自动与机器人的回复进行关联,当需要重新开启一个对话的时候,可以调用ResetConversation,这样对应的机器人对象发过去就是开启了一个新的对话。
如何多用户隔离?比如联合微信机器人使用,可以将一个人或者一个群对应一个Chatbot对象,并且利用id与机器人做关联。
当然这个_clientID需要使用者做唯一性管理
//可以作为隔离不同客户端聊天上下文的凭据,即一个机器人绑定一个客户端

//客户端编号可以是,微信id,qq id,飞书id,亦或者自己开发的软件的用户id

private readonly string _clientID; 

public Chatbot(OpenAISession openAISession, string clientID)

{

    OpenAISession = openAISession;

    _clientID = clientID == null ? Guid.NewGuid().ToString() : clientID;

    ResetConversation();

}

最后构造对话对象,发送到对应api
public async Task GetChatReplyAsync(string prompt)

{

    var conversation = new Conversation();

    conversation.Conversation_id = _conversationId;

    conversation.Parent_message_id = _parentMessageId;

    conversation.Messages = new Message[]

    {

        new Message()

        {

            Content = new Content

            {

                Parts = new string []{ prompt }

            }

        }

    };

    return await GetChatResponseAsync(conversation);

}

/// 

/// 获取响应

/// 

/// 

/// 

/// 服务器返回非200

private async Task GetChatResponseAsync(Conversation conversation)

{

    using (var client = new HttpClient())

    {

        var response = await OpenAISession.PostAsync(_conversation, JsonSerializer.Serialize(conversation, _jsonSerializerOptions));

        if (!response.IsSuccessStatusCode)

        {

            throw new Exception($"Faild to request.StatusCode:{response.StatusCode}");

        }

        var msg = await response.Content.ReadAsStringAsync();

        var data = msg.Split("\n")?.ToList().Where(x => !string.IsNullOrEmpty(x) && !x.Contains("data: [DONE]")).LastOrDefault()?.Substring(5);

        var reply = JsonSerializer.Deserialize(data, _jsonSerializerOptions);

        _conversationId = reply.Conversation_id;

        return reply;

    }

}

效果截图(仅测试)

OpenAISession openAIOptions = new OpenAISession(Session_token, CfClearance, UserAgent);

await openAIOptions.RefreshSessionAsync();

Chatbot chatbot = new Chatbot(openAIOptions);

Console.WriteLine("用c++写个冒泡查询");

var reply = await chatbot.GetChatReplyAsync("用c++写个冒泡查询");

Console.WriteLine(reply.Message.Content.Parts.FirstOrDefault());

源码(欢迎star)https://github.com/BruceQiu1996/NChatGPTRev
转自:BruceNeter
链接:cnblogs.com/qwqwQAQ/p/16981579.html
- EOF -
看完本文有收获?请转发分享给更多人
推荐关注「DotNet」,提升.Net技能 
点赞和在看就是最大的支持❤️

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

上一主题上一主题         下一主题下一主题
QQ手机版小黑屋粤ICP备17165530号

Copyright 2010-2015. All rights reserved. 

微信公众号二维码 抖音二维码 百家号二维码 今日头条二维码哔哩哔哩二维码