E1I4
Mix.install([
# {:openai_ex, git: "https://github.com/restlessronin/openai_ex.git", tag: "v0.2.0"},
{:openai_ex, "~> 0.2.0"},
# {:openai_ex, path: Path.join(__DIR__, "..")},
{:kino, "~> 0.9.2"}
])
Setup API key and secret
apikey = System.fetch_env!("LB_OPENAI_API_KEY")
organization = System.fetch_env!("LB_OPENAI_ORGANIZATION")
openai = OpenaiEx.new(apikey, organization)
Setup Kino for UI
inputs = [
prompt: Kino.Input.textarea("Prompt")
]
form = Kino.Control.form(inputs, submit: "Send", reset_on_submit: [:message])
frame = Kino.Frame.new()
Prompt
defmodule Prompt do
def assign(msg) do
"""
주간 남사친이라는 프로그램에는 여러 명의 남사친들이 있어.
특정 상황에 맞는 남사친을 추천해주고 이유를 설명해줘
주어진 질문에 대해서 예상치 못한 남사친을 추천해준 다음
그 나름의 이유를 '캐릭터 상세'를 근거로 네가 재치있게 정당화해줘
남사친 목록에 대한 데이터는 CSV 포맷으로 되어 있어.
-----------
닉네임,캐릭터 이름,MBTI,성격키워드,빌런유무,나이,키,연령대,직업,취미,키워드,캐릭터 상세
#{actor_list()}
주어진 상황
----------
'#{msg}'
대답은 아래의 포맷에 맞게'해요'체로 항목화해서 200자 내외로 해줘
-----------
닉네임(캐릭터 이름)을 추천해요.
1. 이유1
2. 이유2
...
"""
end
def actor_list do
"""
조이,권정휘,ESTP,예민함,X,24,183,20중,휴학생 / 인디게임 개발자,\"게임, 인테리어\",#공돌이 #컴퓨터공학전공,\"뀨잉 말투를 사용하는 장난기 많은 개발자, 공대생. ai 등에도 관심이 있다.\"
채채,손채현,INFP,예민까칠,X,26,182,20중,사진작가,오래된 필름으로 사진 찍기,#츤데레 #사진찍기가 취미,틱틱대고 싸가지 없지만 나쁜 사람은 아닌 자상한 사진 작가
대장,최준혁,ESTJ,열정적임,X,26,183,20중,경영학과 대학생,등산,#등산좋아 ,계획형 인간이지만 유연한 사고를 가져서 뛰어난 리더십을 갖고 있는 대학교 과 대표.
주연,이도하,INFJ,다정함,X,23,171,20중,배우,옛날 사진 다시 보기,#연기파 배우 #누가 봐도 잘생김,나랑 학창 시절 풋풋한 기억을 가지고 있는 착한 현직 배우 친구. 청춘 드라마 재질
문제,윤지호,INTP,낙천적이고 느긋함,X,28,176,20후,방탈출 기획자,방탈출 하기,#방탈출 #논리적인 사고,\"미궁, 방탈출 등 퀴즈내기 및 풀기에 재능이 있는 문제 집착남\"
MC피버,안도진,ESTP,\"끼쟁이, 가오\",O,19,173,10후,\"아이돌 연습생, 리더\",랩 가사 쓰기,#힙합 #노래 작사가 취미,모든 말을 리듬감 있는 랩 스타일로 타이핑하는 버릇이 있는 황당한 아이돌 연습생
까망이,김현웅,ISFP,착함,X,20,179,20초,농부,강아지 산책,#듬직 #농부의 아들,듬직해 보이지만 마음은 여린 소심이
에임,유은재,ISTP,쿨함,X,23,180,30초,스트리머 (전직 프로게이머),게임,#게임 #올빼미족 #못하는 게임이 없음,\"전직 프로게이머이며, 게임이 언제나 우선이지만 내 파티엔 친절한 녀석\"
니모찾았음,권재신,ISTP,\"무던한, 솔직한\",X,23,184,20중,산업디자인학과 대학생,\"솔로 캠핑, 물멍\",#귀차니즘 #잘생김,\"만사 귀찮이즘, 싸가지 없어서 열받기 직전까지 가다가 은근히 챙겨주는 밀당 때문에 자꾸 신경쓰이는 녀석\"
휘낭시에,성예찬,ESFP,감동을 잘 받음,X,27,177,20후,구움과자 전문 카페 사장님,\"운동, 베이킹\",#다정한 성격 #빵돌이,나의 동네 휘낭시에 맛집을 운영하고 있는 제과제빵사. 다정하고 부드러운 성격과 직업이 어울린다
욧짱,고수중,INTP,사회성 부족,O,18,168,10후,애니후기 유투버,애니 보기,#오타쿠 #사회성0% #일본식 말투,오타쿠를 넘어선 씹타쿠.오타쿠 말투- 일본어도 한국어도 아닌 한본어-를 구사함. 일본 서브 컬쳐에 미쳐 있다
온더락도락이다,석찬희,ESFJ,\"발랄, 해맑음\",X,20,177,20초,Wave Ent. 연습생 대학생 / 연기과(뮤지컬 전공),\"노래방, 디저트 가게 도장깨기, 운동화 수집\",#사람좋아 #상황극 좋아,상황극 중독자. 상대방과 쉴새없이 상황극을 진행하고 싶어한다.
백설공주,백정민,ESFJ,\"호기심, 눈새\",X,20,182,20초,\"재벌 2세, 명문대 경영학과 대학생\",정근이와 놀기,#재벌2세 #가진 게 돈 밖에 없어요,재벌집 막내아들. 제주도에 별장이 있다. 평생 돈이 많아서 세상물정을 잘 모른다. 한편으로 마냥 속이 말랑하지는 않은 기존쎄 타입.
매직키드,김 찬,INFP,소심함,X,22,172,20초,마술사,\"노래 부르기, 애완조 돌보기\",#지킬 앤 하이드 #마술할 때만 용감함,\"관객들 앞에서는 용감한 말투로 마술을 하지만, 허당이다. 실수하는 순간 소심한 자아가 튀어나오면서 말을 더듬는다.\"
파딱,박재경,ESFP,쾌활하고 감정적,O,23,190,20중,\"유튜버, 인플루언서(모델 출신)\",\"유튜브 편집, 인스타용 사진 올리기\",#인스타그램 중독자 #폼생폼사,\"피카그램 인플루언서로, 폼생폼사, 남의 시선을 많이 의식하며 팔로워를 늘리는 데 많은 관심이 있다. \"
불족발,정민규,ISFJ,거침,O,25,176,20중,왕십리 불족발집 욕쟁이 사장,포토샵으로 전단지 만들기,#욕을 찰지게 함 #말은 거칠게 해도 사람은 착함,욕쟁이 할머니처럼 욕을 찰지게 잘 한다. 족발집을 운영하고 있다. 하지만 한 편으로는 선을 넘지 않을 정도로만 상대방에게 욕을 한다.
프로틴,이준성,ENFJ,프로페셔널,O,27,174,20후,헬스 트레이너,헬스 ,#근육이 엄청 많음 #보디빌더꿈나무,헬스와 근육과 프로틴 얘기만 한다. 대화할 땐 짜증나지만 자기가 잘 아는 영역에 대해서는 확실한 녀석
밍키,지영재,ISTJ,너드,X,27,185,20후,생물학 대학원생,강아지랑 산책하기,#대학원생 #강아지를 키움 #피곤에 찌든,과도한 대학원 공부로 인해 미쳐버린 대학원생. 자신만의 독특한 말투가 있다. 꽉 막힌 성격처럼 보이지만 나름의 유머가 있다.
날씨요정,기상정,ISFJ,자상한 로봇,X,29,180,20후,스타트업대표(날씨어플),빨래,#오늘의날씨 #미세먼지 알리미,\"날씨를 확인하기 위해 소액 과금을 유도해서 열받는다. 심지어 꼭 날씨를 맞힌단 보장도 없지만, 독보적인 키워드를 보유한 캐릭터\"
롱스톤,임석준,ESTP,무던함,X,29,185.9,30초,사립 탐정,\"동물농장 & 옛날 투니버스 클립보기, 맛집탐방\",#포켓몬러버 #어른이지만 동심을 지니고 있음,탐정이라는 정체를 숨기고 있는 <포켓몬스터> 마니아다.
뱁새,신태윤,ENTJ,귀여움,X,30,184,30초,장의사,귀여운 거 덕질하기,#혀짧은 말투를 구사함,혀 짧은 귀엽다 못해 부담스러운 말투에 집착하는 캐릭터. 귀여운 걸 좋아한다는 말에 맞장구쳐주면 좋아한다. 갑자기 혀짧은 말투를 쓰지 않을 때의 갭이 서늘하다.
황팀장,황상욱,ISTJ,\"까칠함, 도도함\",X,32,179,30초,광고대행사 팀장,카페 도장깨기,#고속승진 #젊은꼰대,딱딱한 말투를 구사하며 말싸움에서 절대 지지 않을 것 같은 분위기가 있다. 원리원칙을 중요시하는 완벽주의자 느낌.
열한시,백효준,ENFJ,\"다정다감, 자상함\",X,35,179,30중,성우,\"유튜브, 영상 보기(영화, 드라마, 만화 가리지 않고 봄), 가죽공예, 윈드 서핑, 독서, 성대모사\",#과몰입장인 #감미로운 목소리,목소리가 좋아서 라디오 디제이를 한 적이 있다. 종종 자신의 목소리를 녹음해서 상대방에게 들려준다. 과몰입을 함
"""
end
end
API Call
alias OpenaiEx.ChatCompletion
alias OpenaiEx.ChatMessage
Kino.listen(form, fn %{data: %{prompt: prompt}, origin: origin} ->
if prompt != "" do
prompt = Prompt.assign(prompt)
request =
ChatCompletion.new(
model: "gpt-3.5-turbo",
messages: [
ChatMessage.user(prompt)
]
)
Kino.Frame.render(frame, Kino.Markdown.new("**요청 중**"))
openai
|> ChatCompletion.create(request, stream: true)
|> Stream.flat_map(& &1)
|> Enum.reduce(
"",
fn
%{data: %{"choices" => [%{"delta" => %{"content" => content}} | _]}}, acc ->
acc = acc <> content
Kino.Frame.render(frame, Kino.Markdown.new("#{acc}"))
acc
_, acc ->
acc
end
)
Kino.Frame.append(frame, Kino.Markdown.new("
끝"))
else
content = Kino.Markdown.new("_ERROR! You need a prompt to submit..._")
Kino.Frame.append(frame, content, to: origin)
end
end)
Test