jeffdapaz / VisualChatGPTStudio

Add chatGPT functionalities directly on Visual Studio
https://marketplace.visualstudio.com/items?itemName=jefferson-pires.VisualChatGPTStudio
MIT License
210 stars 51 forks source link

Add Proxy: 是否可以新增http代理功能,我所在的地区无法访问访问ChatGPT,我必须使用代理才可以 #17

Closed 52017126 closed 1 year ago

52017126 commented 1 year ago

是否可以新增http代理功能,我所在的地区无法访问访问ChatGPT,我必须使用代理才可以

jeffdapaz commented 1 year ago

Hi,

I'm using this package to make requests to the OpenAI API:

https://github.com/OkGoDoIt/OpenAI-API-dotnet

But unfortunately this package does not support proxy.

52017126 commented 1 year ago

在编写代码时,这个插件的确很方便,但我目前所在国家是中国,我无法访问Open AI API,我必须使用VPN,但这会改变我整个电脑的网络环境,这不是我想要的,我会试着尝试建一个分支出来增加http代理功能

52017126 commented 1 year ago

我查看他的源码了,确实不支持代理,同时他的 HttpClient 是每次请求都会重新创建,并没有复用,这会很慢,你应该考虑重写它的这一部分

jeffdapaz commented 1 year ago

Yes, as I said the library I'm using doesn't provide proxy support.

It would be necessary to use another library or go for an own implementation of HttpClient.

In any case, I'll leave this issue open in case anyone wants to implement this.

PS1: I took the liberty of adding an English description in the title to make it easier to indicate what is intended.

PS2: Thanks for the tip regarding rebuilding the HttpClient. I will fix.

52017126 commented 1 year ago

The third-party library you are using, OpenAI-API dotnet, currently supports proxies and uses the HttpClientFactory method. Please update

jeffdapaz commented 1 year ago

Thanks to advise me. I will check.

jeffdapaz commented 1 year ago

@52017126 ,

I was looking at this and saw that it is indeed possible to inject an instance of HttpClient, and with it the parameterization of the proxy.

But I have some questions and I need a little help.

I've never needed to set up a proxy connection before, and I don't know how to test for a proxy connection to successfully communicate with the OpenAI API.

I saw that to define a proxy connection it would be something like:

HttpClientHandler httpClientHandler = new()
  {                
      Proxy = new WebProxy("http://my-proxy.com:8080"),
      UseProxy = true,
      Credentials = new NetworkCredential("user", "password"),
      UseDefaultCredentials = false
  };

  return new HttpClient(httpClientHandler);

Do you know if that need any more parameters?

Can you tell me a way in which I can test the connection to the API using a proxy?

Or better, can you try for yourself and make a simple POC using this library to communicate with the API using proxy, and after successfully tell me how to do for I can add on the extension?

SundayCoding commented 1 year ago

@jeffdapaz hi,I tested it locally, and it can be accessed normally through the agent. You can refer to it,I added ProxyApi to OptionPageGridGeneral.cs and used it in ChatGPT.cs [Description("Connect to openai through a proxy")] public string ProxyApi { get; set; } = "";

private static void CreateApiHandler(string apiKey,string ProxyApi=null) { if (api.Auth.ApiKey != apiKey) { api.Auth.ApiKey = apiKey; } if (!string.IsNullOrEmpty(ProxyApi)) { api.ApiUrlFormat = ProxyApi + "/{0}/{1}"; } } image

He can access openai normally But now there is another problem. I failed in my attempt to add multilanguage support. I hope you can add some support in your code

SundayCoding commented 1 year ago

@jeffdapaz Sorry, my above question is not about agent, but data forwarding. Since openai cannot be used in my country, there are many access methods, such as agent and forwarding

jeffdapaz commented 1 year ago

Hi @SundayCoding ,

thanks for your help! Your solution looks simple and great!

About translating, what do you need be translated? I'm asking because if you are refering translate the commands, you already can do this by simple translate the commands for any language on options screen.

See this discussion for more details: #8

@52017126 ,

the @SundayCoding solution will works for you too?

SundayCoding commented 1 year ago

@jeffdapaz Sorry that the translation may not be accurate, I hope to provide support for the localization language of the plug-in, such as simplified Chinese, and can you add the most support for Visual Studio 2019? Although Visual Studio 2022 is very powerful, But not everyone is happy with Visual Studio 2022

SundayCoding commented 1 year ago

@jeffdapaz Although I'm a developer myself, I don't know much about plug-in development, so it would be nice to have some basic support, like localization and the bare-minimum framework of vs2019

jeffdapaz commented 1 year ago

@SundayCoding , about translation, so what you want is for the presentation has localization, right?

If so, I think it's impossible. I did a search and found nothing that would indicate this possibility. Much of the texts that are presented in the extension are created at compile time, so for example it would not be possible to translate the texts according to the language defined in Visual Studio for each one.

The only solution I see would be to translate the entire project and create a separate publication for a specific language. In this way, it turns out to be impracticable, as it would be a project (or branch) and a publication on marketplace for each language.

The only texts that can be translated are those that are built at runtime, which are practically just the messages displayed, the tool tips that are there on chat windows and the commands (although these, as I indicated, are already possible to be translated via options).

However, if anyone knows a viable way to add multi language in the presentation, I can implement this possibility.

Or at last case, if someone is available to create a version of the project translated into another language and create a new publication in the marketplace with support for this language, I will not be against it.

About the VS19, please check this issue for more details: #12

52017126 commented 1 year ago

@jeffdapaz @SundayCoding Yes, it is very suitable, but please note that the proxy username and password are not mandatory. It is optional. Thank you for your effort and time

jeffdapaz commented 1 year ago

Hi @52017126 ,

I think with @SundayCoding solution, the username and password coming within the URL, right?

If so, I will published this as soon as posible.

jeffdapaz commented 1 year ago

Guys, I already published a new release with @SundayCoding solution.

Please, give me a feedback if this is working or nothing.

Thanks!

52017126 commented 1 year ago

@jeffdapaz There seems to be a problem, I have checked the code and fixed it. The proxy setting method is incorrect, and I have added the HttpClientFactory creation method, but I am unable to submit this code.

Step 1

private static ChatGPTHttpClientFactory chatGPTHttpClient;
static ChatGPT() {
            chatGPTHttpClient = new ChatGPTHttpClientFactory();
}

Step 2


        private static void CreateApiHandler(string apiKey, string proxy)
        {
            if (api == null)
            {
                api = new(apiKey);
                api.HttpClientFactory = chatGPTHttpClient;
            }
            else if (api.Auth.ApiKey != apiKey)
            {
                api.Auth.ApiKey = apiKey;
            }
            if (!string.IsNullOrWhiteSpace(proxy))
            {
                chatGPTHttpClient.SetProxy(proxy);
            }
        }

Step 3


public class ChatGPTHttpClientFactory : IHttpClientFactory
    {
        private Dictionary<string, HttpClient> m_httpClient = new Dictionary<string, HttpClient>();
        private static readonly object objLock = new object();
        private string m_proxy;

        public HttpClient CreateClient(string name) {
            if(!m_httpClient.TryGetValue(name,out var client)) {
                lock (objLock) {
                    if (!m_httpClient.TryGetValue(name, out client)) {
                        client = CreateHttpClient(CreateMessageHandler(m_proxy));
                        m_httpClient.Add(name, client);
                    }
                }
            }
            return client;
        }

        protected static HttpClient CreateHttpClient(HttpMessageHandler handler) {
            HttpClient lookHttp = new HttpClient(handler);
            lookHttp.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");
            lookHttp.DefaultRequestHeaders.Connection.Add("keep-alive");
            lookHttp.Timeout = new TimeSpan(0, 0, 120);
            return lookHttp;
        }

        protected static HttpMessageHandler CreateMessageHandler(string proxy = null) {
            var handler = new HttpClientHandler();
            handler.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
            handler.UseCookies = true;
            handler.AllowAutoRedirect = true;
            handler.ServerCertificateCustomValidationCallback = (a, b, c, d) => true;
            handler.MaxConnectionsPerServer = 256;
            handler.SslProtocols =
                System.Security.Authentication.SslProtocols.Tls13 |
                System.Security.Authentication.SslProtocols.Tls12 |
                System.Security.Authentication.SslProtocols.Tls11 |
                System.Security.Authentication.SslProtocols.Tls;

            if (!string.IsNullOrEmpty(proxy)) {
                handler.Proxy = new WebProxy(new Uri(proxy));
            }

            return handler;
        }

        public void SetProxy(string proxy) {
            if(proxy != m_proxy) {
                                m_proxy = proxy;
                var list = m_httpClient.ToArray();
                foreach (var item in list) {
                    item.Value.Dispose();
                    m_httpClient.Remove(item.Key);
                }

            }
        }
}
jeffdapaz commented 1 year ago

Hi @52017126, thanks for your feedback, and for provided a new solution.

But unfortunately now I'm on vacation in another country without access to a computer where I can program.

I am be able to release I new version more on less on May 20.

jeffdapaz commented 1 year ago

I already have the solution provided by @52017126 on my side.

I will publish it shortly in the next release.

If the solution is still not suitable, feel free to give feedback and open this issue again.