Closed8
Azure Functions と OpenAI API を使って Line 返答サービスを作ってみる
とりあえず Messaging API のアカウント作った
次は Functions かな。無料枠でええかとおもったけど無料枠ないやんけw
VSで試すか
それっぽいコード
まずはFunction本体。System.Text.Jsonで実装してみたやつ。
private static readonly string _messagingApiUrl = "https://api.line.me/v2/bot/message/reply";
private static readonly string _accessToken = "";
private static readonly string _channelSecret = "";
private static readonly string _apiKey = "";
private static HttpClient _httpClient = new HttpClient();
[FunctionName("LineReply")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req,
ILogger log)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
req.Headers.TryGetValue("X-Line-Signature", out var xLineSignature);
log.LogInformation($"Body : {requestBody}");
var json = System.Text.Json.JsonSerializer.Deserialize<LineMessageReceiveJson>(requestBody);
log.LogInformation($"Message: {json.events[0].message.text}");
if (IsSingature(xLineSignature, requestBody, _channelSecret))
{
if (json.events[0].type == "message")
{
var api = new OpenAIAPI(_apiKey);
var chat = api.Chat.CreateConversation();
var prompt = json.events[0].message.text;
chat.AppendUserInput(prompt);
var result = await chat.GetResponseFromChatbotAsync();
// ChatGPTから返答
await SendTextReplyAsync(json.events[0].replyToken, result);
return new OkResult();
}
}
return new BadRequestResult();
}
private static async Task SendTextReplyAsync(string replyToken, string message)
{
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _accessToken);
var response = await _httpClient.PostAsJsonAsync<LineTextReplyJson>(_messagingApiUrl, new LineTextReplyJson()
{
replyToken = replyToken,
messages = new List<Message>()
{
new Message(){
type = "text",
text = message
}
}
});
response.EnsureSuccessStatusCode();
}
private static bool IsSingature(string signature, string text, string key)
{
var textBytes = Encoding.UTF8.GetBytes(text);
var keyBytes = Encoding.UTF8.GetBytes(key);
using (HMACSHA256 hmac = new HMACSHA256(keyBytes))
{
var hash = hmac.ComputeHash(textBytes, 0, textBytes.Length);
var hash64 = Convert.ToBase64String(hash);
return signature == hash64;
}
}
あとはJsonのプロパティ
受信用
public class LineMessageReceiveJson
{
public string destination { get; set; }
public List<Event> events { get; set; }
}
public class Event
{
public string replyToken { get; set; }
public string type { get; set; }
public object timestamp { get; set; }
public Source source { get; set; }
public Message message { get; set; }
}
public class Message
{
public string id { get; set; }
public string type { get; set; }
public string text { get; set; }
}
public class Source
{
public string type { get; set; }
public string userId { get; set; }
}
返信用(Messageクラスは使いまわし)
public class LineTextReplyJson
{
public string replyToken { get; set; }
public List<Message> messages { get; set; }
public bool notificationDisabled { get; set; }
}
参考になったサイト
IsSingature の判定がないと返信してくれないみたいなので、動かないなぁと思ったらこれの実装忘れを確認したほうがよさそう。
あとは「関数のURLの取得」からリンクを発行して、Webhookに設定。Webhookの利用をオンにすることをわすれずに。
実行結果(良きかな~)
このスクラップは2023/04/22にクローズされました