SK入门第一篇(设置baseurl)

2024-01-15 07:52

本文主要是介绍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 kernelvar 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标记,修改域名部分,修改端口,即部分修改。

这篇关于SK入门第一篇(设置baseurl)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/608176

相关文章

从入门到精通详解Python虚拟环境完全指南

《从入门到精通详解Python虚拟环境完全指南》Python虚拟环境是一个独立的Python运行环境,它允许你为不同的项目创建隔离的Python环境,下面小编就来和大家详细介绍一下吧... 目录什么是python虚拟环境一、使用venv创建和管理虚拟环境1.1 创建虚拟环境1.2 激活虚拟环境1.3 验证虚

MySQL设置密码复杂度策略的完整步骤(附代码示例)

《MySQL设置密码复杂度策略的完整步骤(附代码示例)》MySQL密码策略还可能包括密码复杂度的检查,如是否要求密码包含大写字母、小写字母、数字和特殊字符等,:本文主要介绍MySQL设置密码复杂度... 目录前言1. 使用 validate_password 插件1.1 启用 validate_passwo

Java List 使用举例(从入门到精通)

《JavaList使用举例(从入门到精通)》本文系统讲解JavaList,涵盖基础概念、核心特性、常用实现(如ArrayList、LinkedList)及性能对比,介绍创建、操作、遍历方法,结合实... 目录一、List 基础概念1.1 什么是 List?1.2 List 的核心特性1.3 List 家族成

c++日志库log4cplus快速入门小结

《c++日志库log4cplus快速入门小结》文章浏览阅读1.1w次,点赞9次,收藏44次。本文介绍Log4cplus,一种适用于C++的线程安全日志记录API,提供灵活的日志管理和配置控制。文章涵盖... 目录简介日志等级配置文件使用关于初始化使用示例总结参考资料简介log4j 用于Java,log4c

史上最全MybatisPlus从入门到精通

《史上最全MybatisPlus从入门到精通》MyBatis-Plus是MyBatis增强工具,简化开发并提升效率,支持自动映射表名/字段与实体类,提供条件构造器、多种查询方式(等值/范围/模糊/分页... 目录1.简介2.基础篇2.1.通用mapper接口操作2.2.通用service接口操作3.进阶篇3

Python自定义异常的全面指南(入门到实践)

《Python自定义异常的全面指南(入门到实践)》想象你正在开发一个银行系统,用户转账时余额不足,如果直接抛出ValueError,调用方很难区分是金额格式错误还是余额不足,这正是Python自定义异... 目录引言:为什么需要自定义异常一、异常基础:先搞懂python的异常体系1.1 异常是什么?1.2

Python实现Word转PDF全攻略(从入门到实战)

《Python实现Word转PDF全攻略(从入门到实战)》在数字化办公场景中,Word文档的跨平台兼容性始终是个难题,而PDF格式凭借所见即所得的特性,已成为文档分发和归档的标准格式,下面小编就来和大... 目录一、为什么需要python处理Word转PDF?二、主流转换方案对比三、五套实战方案详解方案1:

Spring WebClient从入门到精通

《SpringWebClient从入门到精通》本文详解SpringWebClient非阻塞响应式特性及优势,涵盖核心API、实战应用与性能优化,对比RestTemplate,为微服务通信提供高效解决... 目录一、WebClient 概述1.1 为什么选择 WebClient?1.2 WebClient 与

python设置环境变量路径实现过程

《python设置环境变量路径实现过程》本文介绍设置Python路径的多种方法:临时设置(Windows用`set`,Linux/macOS用`export`)、永久设置(系统属性或shell配置文件... 目录设置python路径的方法临时设置环境变量(适用于当前会话)永久设置环境变量(Windows系统

Go语言编译环境设置教程

《Go语言编译环境设置教程》Go语言支持高并发(goroutine)、自动垃圾回收,编译为跨平台二进制文件,云原生兼容且社区活跃,开发便捷,内置测试与vet工具辅助检测错误,依赖模块化管理,提升开发效... 目录Go语言优势下载 Go  配置编译环境配置 GOPROXYIDE 设置(VS Code)一些基本