ChatGPT AKKA 연계 활용편 |
다양한 프롬프트를 테스트해야하기때문에 ChatGPT(OpenAI) API를 이용하는 유닛테스트기를 먼저 생성
일반적인 응답속도가 30초 이상이여서 이대로는 서비스로 활용불가
프롬프트 데이터
프롬프트도 중요하지만, 프롬프트에 활용된 데이터에 따라 인사이트가 달라지며 시즌별로 최신을 반영해야합니다. 실시간일 필요는 없습니다.
어떠한 인사이트인경우 랭킹이 높은것보다 낮은것이 유용할수 있으며, 항상 1위를 차지하는 고정 단어일경우 제외 처리하는것이 유용할수도 있습니다.
가령 상담시스템에서 "상담" 이란 단어는 아무런 의미가 없을수 있습니다.
Messages = new List<ChatMessage>() { ChatMessage.FromSystem(metaData.system), ChatMessage.FromAssistant(metaData.assist), ChatMessage.FromUser(prompt), } |
GTP API는 System/Assist/Prompt 3가지 유형으로 구분하여 메시지 작성이 가능하며
한꺼번에 질문을 할수도 있지만 다음과 구분하여 프롬프트를 작성하면 효율적이다.
구분없이 데이터+질문을 한꺼번에해도 GPT가 구분하여 답변을 할수 있지만 GPT가 이해할수 있게 이 맥락을 더 잘 만들어야한다.
시스템의 문구와 사용자 질문의도의 전문영역이 안맞으면 다음과 같이 답변하기도합니다. >> 죄송합니다, 저는 상담 시스템 데이터만 알고 있기 때문에 제품의 품질 인사이트를 분석하는 것은 제한된 역할이라 할 수 있습니다. 답변으로 유추해보면 system에서 조금더 전문적인 AI 영역을 선택하는것 같다. System에서 전문가를 선택하는것으로 보인다~ |
ChatGPT의 응답시간이 비교적 길기때문에~ API 이용중 GTP의 결과를 검색엔진화하고
사용자는 검색엔진을 통해 빠른 결과를 획득하는 하이브리드 전략입니다. 프롬프트가 어느정도 유형화가 되었을때 활용할수 있습니다.
물론 ChatGpt와 비슷한 수준에 자연어를 통한 사용자의도 파악하는 AI기술이 있다고 하면 더 높은 수준으로 검색 기술과 연동할수 있습니다.
var elkCacheData = await _searchService.FindGptReultByFilter(gPTMetaData, 20); GPTResponse gPTResponse = new GPTResponse(); if (elkCacheData.Count > 0) { gPTResponse.FromGPTResutEntity(elkCacheData[0]); gPTResponse.isCache = true; GPTResultEntityCmd gPTResultEntityCmd = new GPTResultEntityCmd() { command = "save", prompt = promptBuild.ToString(), gPTMetaData = gPTMetaData }; _actorBridge.Tell(gPTResultEntityCmd); } else { gPTResponse = await _gPTEngine.GetChatCompletions(promptBuild.ToString(), gPTMetaData); gPTResponse.isCache = false; } return gPTResponse; |
여기서 응답결과가 늦은 GPT를 호출하고 결과를 저장하기 위해 API 레벨에서 스레드를 생성하고 저장하는 방식을 이용하면 안되며
API의 라이프 사이클은 응답이 빠르게 완료된 시점 자원을 해제해야하기때문에 여기서 생성한 스레드에 대한 라이프를 책임질수 없으며 다양한 사이드 이펙트가 발생할수 있습니다.
액터는 AkkaSystem에 의해 백그라운드에서 ActorDispatch에 의해 이벤트가 발생할때 조건이 맞을때 작동을 하며 독립적으로 Task를 수행할수 있습니다.
namespace MorphemeApi.Actors { public class GptEntityActor : ReceiveActor { private readonly ILoggingAdapter logger = Context.GetLogger(); private readonly GPTEngine _gPTEngine; public GptEntityActor(GPTEngine gPTEngine) { logger.Info($"Create GraphEventActor:{Context.Self.Path.Name}"); _gPTEngine = gPTEngine; ReceiveAsync<GPTResultEntityCmd>(async message => { try { await _gPTEngine.SaveChatCompletions(message.prompt, message.gPTMetaData); } catch (Exception ex) { logger.Error(ex.Message); } }); } } } |
Stream 연결
var serviceScopeFactory = new Mock<IServiceScopeFactory>(); serviceScopeFactory.Setup(x => x.CreateScope()).Returns(serviceScope.Object); IActorRef throttleWork = _actorSystem.ActorOf(Props.Create(() => new ThrottleActor(500, 30000))); GPTEngine gPTEngine = new GPTEngine(lightAkkaService, configuration); var gptEntityActor = _actorSystem.ActorOf(Props.Create(() => new GptEntityActor(gPTEngine)), "gptEntityActor"); //Stream 연결 : throttleWork -> fsmActor -> batchActor throttleWork.Tell(new SetTarget(gptEntityActor)); throttleWork.Tell(new GPTResultEntityCmd(){....}); |
Throttle(TPS제어) 에 연결하여 GPT를 호출하는 TPS를 제어할수도 있으며, 발생한 데이터를 이벤트별 저장이아닌 실시간에 가까운 데이터를 모아서 벌크처리도 가능하게 됩니다.
Akka Stream에 관련한 작동가능 코드는 다음 저장소에서 확인할수 있으며 자바/닷넷에서 동일한 컨셉으로 이용가능합니다.
CRM 서비스와 관련한 다양한 GPT의 응답을 단어별로 랭킹~ CRM에서 중요한 키워딩을 유형및 시즌별로 파악할수가 있습니다.
참고링크 :