SK入门第一篇(设置baseurl)

问题说明

之前在一些公众号就看到了关于SK的开发文章,然后说自己也试试看。然后就遇到一个关于如何设置baseurl的问题。啥意思呢?同样是SK,用python语言的话,OpenAI的baseurl是可以直接设置的,但是在C#下没法直接设置。

然后,开始调试,找野路子…

解决方式1

官方案例初始化OpenAIClient的构造函数,只有一个OpenAIKey的参数

但是,可以看到,这个构造函数,其实是调用了另一个构造函数,参数有Endpoint(即baseurl信息)、OpenAIKey,以及OPenAIClientOptions。

这个时候,脑海里有了一个想法,我通过下面的构造函数搞起来不就行了,为了方便后续统一调整,自己搞一个通用类实现

public class OpenAIClientExtend
{
    /// <summary>
    /// 创建一个OpenAIClient对象,通过apikey和baseurl
    /// </summary>
    /// <param name="openAIApiKey"></param>
    /// <param name="openAIApiKeyBaseUrl"></param>
    /// <returns></returns>
    public static OpenAIClient CreateOpenAIClient(string openAIApiKey, string openAIApiBaseUrl)
    {
        OpenAIClient openAIClient = new OpenAIClient(new Uri(openAIApiBaseUrl), CreateDelegatedToken(openAIApiKey), new OpenAIClientOptions());
        return openAIClient;
    }

    /// <summary>
    /// 直接把OPenAIClient代码的相关逻辑拿来,通过apikey生成token
    /// </summary>
    /// <param name="token">实际这里是OPenAIKey</param>
    /// <returns></returns>
    private static TokenCredential CreateDelegatedToken(string token)
    {
        var accessToken = new AccessToken(token, DateTimeOffset.Now.AddDays(180));
        return DelegatedTokenCredential.Create((_, _) => accessToken);
    }

试了下,发现还是不行啊。。

然后又回到那个构造函数那里,想起来它在调用了另一个构造函数后,其实还写了一句:

_isConfiguredForAzureOpenAI = false;

看字面意思,是否是针对AzureOpenAI设置,默认值是true,那就知道为啥了,不过看了下这个字段是private,那么只能通过反射修改了。

//通过反射冬天修改私有字段,否则按照原来的逻辑,会初始化AzureOpenAI,导致无法使用报错
OpenAIClientExtend.ModifyObj<OpenAIClient>(openAIClient, "_isConfiguredForAzureOpenAI", false);

 具体修改实例类字段的代码如下:

public static void ModifyObj<T>(object obj,string filedName,object newVal)
{
    Type type = typeof(T);
    FieldInfo? field = type.GetField(filedName, BindingFlags.NonPublic | BindingFlags.Instance);

    if (field != null && field.IsPrivate)
    {
        object? value = field.GetValue(obj); // 获取私有字段的值

        Console.WriteLine("原始私有字段的值为:" + value);

        field.SetValue(obj, newVal); // 修改私有字段的值

        Console.WriteLine("修改后的私有字段的值为:" + field.GetValue(obj));
    }
}

这个时候,baseurl的设置终于生效了,可以愉快的开始后面的coding了

完整的OPenAIClient初始化代码

public static Kernel CreateKernel()
{
    OpenAIClient openAIClient = OpenAIClientExtend.CreateOpenAIClient(OPENAI_API_KEY, OPENAI_BASE_URL);
    //通过反射冬天修改私有字段,否则按照原来的逻辑,会初始化AzureOpenAI,导致无法使用报错
    OpenAIClientExtend.ModifyObj<OpenAIClient>(openAIClient, "_isConfiguredForAzureOpenAI", false);

    // Create a kernel
    var builder = Kernel.CreateBuilder();
    // Add a text or chat completion service using either:
    // builder.Services.AddAzureOpenAIChatCompletion()
    // builder.Services.AddAzureOpenAITextGeneration()

    //IServiceCollection serviceCollection = builder.Services.AddLogging(c => c.SetMinimumLevel(LogLevel.Trace).AddDebug());
    //这里使用的是OpenAI的聊天模型,不太理想,需要改进,更好的方法是在Add方法中实例化大模型对象
    builder.Services.AddOpenAIChatCompletion("gpt-3.5-turbo", openAIClient);
    // builder.Services.AddOpenAITextGeneration()

    builder.Plugins.AddFromType<AuthorEmailPlanner>();
    builder.Plugins.AddFromType<EmailPlugin>();

    var kernel = builder.Build();

    return kernel;
}

解决方式2

隔了有几天,在公众号看到有大佬也提到了这个问题,不过还是大佬技高一筹,解决方式更好,直接上代码。 

    var kernel = Kernel.CreateBuilder()
.AddOpenAIChatCompletion(
     modelId: "gpt-3.5-turbo",
     apiKey: Util.OPENAI_API_KEY,
     httpClient: new HttpClient(new MyOpenAIHandler())
).Build();

可以看到,最后一个参数httpClient即动态设置baseurl的

/// <summary>
/// 自定义baseurl
/// </summary>
class MyOpenAIHandler : DelegatingHandler
{

    public MyOpenAIHandler()
        : base(new HttpClientHandler())
    {
    }

    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var newUriBuilder = new UriBuilder(request.RequestUri);
        newUriBuilder.Scheme = "https";
        newUriBuilder.Host = "api.xx.com";
        //newUriBuilder.Port = 21000;

        request.RequestUri = newUriBuilder.Uri;
        return base.SendAsync(request, cancellationToken);
    }
}

测试可用,大概思路,动态修改了原来OPenAI的base地址。

不过和方式1的差别,方式1 直接修改完整地址,方式2在OPenAI地址基础上,修改了http或https标记,修改域名部分,修改端口,即部分修改。

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值