核心步骤:
1. 申请TOKEN
2. 创建Assistant
3. 创建Thread
4. 创建Message
5. 创建Run
封装代码:
Assistant.cs
using System;
using Microsoft.AspNetCore.Mvc;
using System.Net;
using System.Text;
namespace Bodhi.Utility.OPENAI
{
public class Assistants
{
public Assistants()
{
}
/// <summary>
/// 创建助手
/// </summary>
/// <param name="name">名称</param>
/// <param name="instructions">指令</param>
/// <param name="model">模型</param>
/// <returns></returns>
public static string Create(string? name, string? instructions, string? model)
{
// 构造TOOLS
List<Dictionary<string, object>> tools = new List<Dictionary<string, object>>();
Dictionary<string, object> tool = new Dictionary<string, object>();
tool.Add("type", "retrieval");
tools.Add(tool);
// 构造请求参数
SortedDictionary<string, object> dic = new SortedDictionary<string, object>();
dic.Add("name", name);
dic.Add("instructions", instructions);
dic.Add("tools", tools);
dic.Add("model", model);
var data = Newtonsoft.Json.JsonConvert.SerializeObject(dic);
var url = "https://api.openai.com/v1/assistants";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/json;";
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36";
request.Accept = "application/json";
request.Headers.Add("OpenAI-Beta", "assistants=v1");
request.Headers.Add("Authorization", "Bearer " + Config.API_KEY);
byte[] paramJsonBytes;
paramJsonBytes = Encoding.UTF8.GetBytes(data);
request.ContentLength = paramJsonBytes.Length;
Stream writer;
try
{
writer = request.GetRequestStream();
}
catch (Exception)
{
writer = null;
}
writer.Write(paramJsonBytes, 0, paramJsonBytes.Length);
writer.Close();
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
response = ex.Response as HttpWebResponse;
}
Stream resStream = response.GetResponseStream();
StreamReader reader = new StreamReader(resStream);
return reader.ReadToEnd();
}
}
}
Threads.cs
using System;
using System.Net;
using System.Text;
namespace Bodhi.Utility.OPENAI
{
public class Threads
{
public Threads()
{
}
/// <summary>
/// 创建线程
/// </summary>
/// <returns></returns>
public static string Create()
{
var url = "https://api.openai.com/v1/threads";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/json;";
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36";
request.Accept = "application/json";
request.Headers.Add("OpenAI-Beta", "assistants=v1");
request.Headers.Add("Authorization", "Bearer " + Config.API_KEY);
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
response = ex.Response as HttpWebResponse;
}
Stream resStream = response.GetResponseStream();
StreamReader reader = new StreamReader(resStream);
return reader.ReadToEnd();
}
}
}
Messages.cs
using System;
using System.Net;
using System.Text;
namespace Bodhi.Utility.OPENAI
{
public class Messages
{
public Messages()
{
}
/// <summary>
/// 创建消息
/// </summary>
/// <param name="thread_no">线程编号</param>
/// <param name="content">提问内容</param>
/// <returns></returns>
public static string Create(string thread_no, string content)
{
// 构造请求参数
SortedDictionary<string, object> dic = new SortedDictionary<string, object>();
dic.Add("role", "user"); // 目前只支持user
dic.Add("content", content);
var data = Newtonsoft.Json.JsonConvert.SerializeObject(dic);
var url = "https://api.openai.com/v1/threads/" + thread_no + "/messages";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/json;";
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36";
request.Accept = "application/json";
request.Headers.Add("OpenAI-Beta", "assistants=v1");
request.Headers.Add("Authorization", "Bearer " + Config.API_KEY);
byte[] paramJsonBytes;
paramJsonBytes = Encoding.UTF8.GetBytes(data);
request.ContentLength = paramJsonBytes.Length;
Stream writer;
try
{
writer = request.GetRequestStream();
}
catch (Exception)
{
writer = null;
}
writer.Write(paramJsonBytes, 0, paramJsonBytes.Length);
writer.Close();
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
response = ex.Response as HttpWebResponse;
}
Stream resStream = response.GetResponseStream();
StreamReader reader = new StreamReader(resStream);
return reader.ReadToEnd();
}
/// <summary>
/// 获取消息列表
/// </summary>
/// <param name="thread_no"></param>
/// <returns></returns>
public static string List(string thread_no)
{
var url = "https://api.openai.com/v1/threads/" + thread_no + "/messages";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "GET";
request.ContentType = "application/json;";
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36";
request.Accept = "application/json";
request.Headers.Add("OpenAI-Beta", "assistants=v1");
request.Headers.Add("Authorization", "Bearer " + Config.API_KEY);
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
response = ex.Response as HttpWebResponse;
}
Stream resStream = response.GetResponseStream();
StreamReader reader = new StreamReader(resStream);
return reader.ReadToEnd();
}
}
}
Run.cs
using System;
using System.Net;
using System.Text;
namespace Bodhi.Utility.OPENAI
{
public class Run
{
public Run()
{
}
/// <summary>
/// 执行助手
/// </summary>
/// <param name="thread_no">线程编号</param>
/// <param name="assistant_no">助手编号</param>
/// <returns></returns>
public static string Create(string thread_no, string assistant_no)
{
// 构造请求参数
SortedDictionary<string, object> dic = new SortedDictionary<string, object>();
dic.Add("assistant_id", assistant_no);
var data = Newtonsoft.Json.JsonConvert.SerializeObject(dic);
var url = "https://api.openai.com/v1/threads/"+ thread_no + "/runs";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/json;";
request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3100.0 Safari/537.36";
request.Accept = "application/json";
request.Headers.Add("OpenAI-Beta", "assistants=v1");
request.Headers.Add("Authorization", "Bearer " + Config.API_KEY);
byte[] paramJsonBytes;
paramJsonBytes = Encoding.UTF8.GetBytes(data);
request.ContentLength = paramJsonBytes.Length;
Stream writer;
try
{
writer = request.GetRequestStream();
}
catch (Exception)
{
writer = null;
}
writer.Write(paramJsonBytes, 0, paramJsonBytes.Length);
writer.Close();
HttpWebResponse response;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
response = ex.Response as HttpWebResponse;
}
Stream resStream = response.GetResponseStream();
StreamReader reader = new StreamReader(resStream);
return reader.ReadToEnd();
}
}
}
Config.cs
using System;
namespace Bodhi.Utility.OPENAI
{
public class Config
{
public Config()
{
}
/// <summary>
/// OPENAI网站创建的KEY
/// </summary>
public static string API_KEY = "sk-5B308g**********************riyQYt2";
}
}
前端调用提问业务逻辑如下:
var result = Utility.OPENAI.Threads.Create();
log.Information("result=" + result);
// 第1步:处理OPENAI接口返回信息
if (!string.IsNullOrEmpty(result))
{
JObject obj = (JObject)JsonConvert.DeserializeObject(result)!;
if (obj != null)
{
var thread_no = obj["id"]!.ToString();
var thread_object = obj["object"];
var created_at = obj["created_at"];
var metadata = obj["metadata"];
DateTime dt_created_at = DateTime.Now;
try
{
dt_created_at = CommonHelper.ToLocalTimeDateBySeconds(Convert.ToInt64(created_at));
}
catch (Exception ex)
{
log.Fatal(ex, " -> dt_created_at");
}
// 新增线程
_context.bodhi_ai_threads.Add(new AiThreads()
{
member_id = 1,
thread_no = thread_no,
thread_object = thread_object!.ToString(),
meta_data = metadata!.ToString(),
json_data = result,
thread_remark = "",
created_at = dt_created_at,
});
_context.SaveChanges();
// 第2步:请求OPENAI接口创建Message
try
{
var message_content = string.IsNullOrEmpty(aiMessages.message_content) ? "" : aiMessages.message_content;
var result_message = Utility.OPENAI.Messages.Create(thread_no, message_content);
log.Information("result_message=" + result_message);
// 处理OPENAI接口返回信息
if (!string.IsNullOrEmpty(result_message))
{
JObject obj2 = (JObject)JsonConvert.DeserializeObject(result_message)!;
if (obj2 != null)
{
var message_no = obj2["id"];
var message_object = obj2["object"];
var message_created_at = obj2["created_at"];
var message_role = obj2["role"];
DateTime dt_message_created_at = DateTime.Now;
try
{
dt_message_created_at = CommonHelper.ToLocalTimeDateBySeconds(Convert.ToInt64(created_at));
}
catch (Exception ex)
{
log.Fatal(ex, " -> dt_message_created_at");
}
// 从OPENAI获取接口数据后更新本地数据
var item = _context.bodhi_ai_messages.FirstOrDefault(t => t.message_id == aiMessages.message_id);
if (item != null)
{
item.thread_no = thread_no;
item.message_no = message_no!.ToString();
item.message_role = message_role!.ToString();
item.json_data = result_message;
item.message_remark = dt_message_created_at.ToString();
_context.bodhi_ai_messages.Update(item);
_context.SaveChanges();
log.Information("item=" + item);
}
}
}
}
catch (Exception ex)
{
log.Fatal(ex, " -> 请求OPENAI接口创建Message");
}
// 第3步:请求OPENAI接口创建Run
try
{
var ai_assistants = _context.bodhi_ai_assistants.FirstOrDefault(t => t.assistant_id == aiMessages.assistant_id);
if (ai_assistants != null)
{
var assistant_no = string.IsNullOrEmpty(ai_assistants.assistant_no) ? "" : ai_assistants.assistant_no;
var result_run = Utility.OPENAI.Run.Create(thread_no, assistant_no);
log.Information("result_run=" + result_run);
// 处理OPENAI接口返回信息
if (!string.IsNullOrEmpty(result_run))
{
JObject obj2 = (JObject)JsonConvert.DeserializeObject(result_run)!;
if (obj2 != null)
{
var run_no = obj2["id"];
var run_object = obj2["object"];
var run_created_at = obj2["created_at"];
var run_role = obj2["role"];
var assistant_id = obj2["assistant_id"];
var thread_id = obj2["thread_id"];
var status = obj2["status"];
var started_at = obj2["started_at"];
var expires_at = obj2["expires_at"];
var cancelled_at = obj2["cancelled_at"];
var failed_at = obj2["failed_at"];
var completed_at = obj2["completed_at"];
var last_error = obj2["last_error"];
var model = obj2["model"];
var instructions = obj2["instructions"];
var file_ids = obj2["file_ids"];
var run_metadata = obj2["metadata"];
// 新增执行助手任务
_context.bodhi_ai_run.Add(new AiRun()
{
run_no = run_no!.ToString(),
run_object = run_object!.ToString(),
thread_no = thread_no,
assistant_no = assistant_no,
run_status = status!.ToString(),
started_at = started_at == null ? "" : started_at!.ToString(),
expires_at = started_at == null ? "" : expires_at!.ToString(),
cancelled_at = started_at == null ? "" : cancelled_at!.ToString(),
failed_at = started_at == null ? "" : failed_at!.ToString(),
completed_at = started_at == null ? "" : completed_at!.ToString(),
last_error = last_error == null ? "" : last_error.ToString(),
run_model = model!.ToString(),
file_ids = file_ids!.ToString(),
meta_data = metadata!.ToString(),
json_data = result,
created_at = DateTime.Now,
});
_context.SaveChanges();
}
}
}
}
catch (Exception ex)
{
log.Fatal(ex, " -> 请求OPENAI接口创建Run");
}
}
}
提交问题后,查询接口回复消息如下:
var ai_messages = _context.bodhi_ai_messages.FirstOrDefault(t => t.message_id == id);
var result_message_reply = Utility.OPENAI.Messages.List(ai_messages.thread_no);
log.Information("result_message_reply=" + result_message_reply);
// 处理OPENAI接口返回信息
if (!string.IsNullOrEmpty(result_message_reply))
{
JObject obj2 = (JObject)JsonConvert.DeserializeObject(result_message_reply)!;
if (obj2 != null)
{
foreach (var item in obj2["data"])
{
var message_no = item["id"]!.ToString();
var message_object = item["object"]!.ToString();
var thread_id = item["thread_id"]!.ToString();
var role = item["role"]!.ToString();
var content = item["content"]!.ToString();
var assistant_id = item["assistant_id"];
var run_id = item["run_id"];
var result_created_at = item["created_at"];
DateTime dt_message_created_at = DateTime.Now;
try
{
dt_message_created_at = CommonHelper.ToLocalTimeDateBySeconds(Convert.ToInt64(result_created_at));
}
catch (Exception ex)
{
log.Fatal(ex, " -> result_created_at");
}
if (role.Contains("assistant"))
{
// 处理内容
var message_type = "";
var message_text = "";
try
{
JArray obj = (JArray)JsonConvert.DeserializeObject(content)!;
foreach (var item2 in obj)
{
message_type = item2["type"]!.ToString();
message_text = item2["text"]!["value"]!.ToString();
}
}
catch (Exception ex)
{
log.Fatal(ex, " -> 处理内容");
}
log.Information("message_type=" + message_type + ",message_text=" + message_text);
// 新增执行助手任务
if (!_context.bodhi_ai_message_results.Any(t => t.message_id == id))
{
_context.bodhi_ai_message_results.Add(new AiMessageResults()
{
message_id = id,
message_no = message_no,
message_object = message_object,
thread_no = thread_id!.ToString(),
message_role = role!.ToString(),
message_type = message_type,
message_text = message_text,
file_ids = "",
meta_data = "",
json_data = result_message_reply,
message_time = dt_message_created_at,
assistant_no = assistant_id!.ToString(),
run_no = run_id!.ToString(),
created_at = DateTime.Now,
});
_context.SaveChanges();
}
}
}
}
}