[๐งโ๐ป] Keymory ๊ฐ๋ฐ ์ผ์ง #8: DiaryPage ๊ฐ์ ํค์๋ ์์คํ ๊ตฌ์ถ, AI ์ฝ๋ฉํธ ์บ๋ฆญํฐ ์ค์
โจ GPT์ ์์ฝ ใ
DiaryPage ๊ฐ์ ํค์๋ ์ ํ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๊ณ , AI ์ฝ๋ฉํธ์ ์บ๋ฆญํฐ ์ค์ ์ ์ ์ฉํ์ฌ ์์ฐ์ค๋ฌ์ด ๋ฐ์์ ๊ตฌํํจ.
๐ป ๊ฐ๋ฐ ์ผ์ง
โฐ ์ค๋ ํ ์ผ
- โ
DiaryPage:
๊ฐ์ ํค์๋
ChoiceChip, TextField ์ถ๊ฐ- โ ์์ ฏ ๋ง๋ค๊ธฐ
- โ
diaries DB Field ์ถ๊ฐ: mood_keywords (
List <String>
), mood_keywords_description (String) - โ
diaries Page State ์ถ๊ฐ: moodKeywordsSelected (
List <String>
) - โ
OnPageLoad: ์ถ๊ฐํ ๋ณ์๋ค ์ ๋ฌํ๊ธฐ
- โ
ChoiceChipRate(5~1): diariesDoc.mood_keywords์ ๊ฐ๋ค์ ๊ฐ ํด๋นํ๋ ChoiceChip์ผ๋ก ์ ๋ฌ.
- MoodKeywordRate5Options, โฆ, MoodKeywordRate1Options
List <String>
์ App Constant ๊ฐ์ผ๋ก ์ ์- Enum์ ์์ด๋ง ์ง์๋๋ฏ๋ก, ๋ฒ์ญ ๊ธฐ๋ฅ ์จ์ผ ํจ. ๋๋ฌด ๋ณต์กํ๋ฏ๋ก ํ๋ฝ.
- Define Options Var: AppConstant.moodKeywordRate5Options (
List <String>
) - Initially Selected: updateChoiceChipSelected
- MoodKeywordRate5Options, โฆ, MoodKeywordRate1Options
- โ
Create CustomFunction
updateMoodKeywordsSelected
- On Page Load: Select all matching items in RateOptions List
List<String> updateChoiceChipSelected( List<String> moodKeywordsSelected, // ํ์ฌ ์ ํ๋ ํค์๋ ๋ฆฌ์คํธ List<String> moodKeywordRateOptions, // ํ์ฌ Rate์ ์ ํ ๊ฐ๋ฅํ ์ต์ ๋ค ) { // ์๋ก์ด ๋ฆฌ์คํธ๋ฅผ ์์ฑํ์ฌ ๋ถ๋ณ์ฑ ์ ์ง return List<String>.from( moodKeywordsSelected.where((item) => moodKeywordRateOptions.contains(item)) ); }
- โ
ChoiceChipRate(5~1): diariesDoc.mood_keywords์ ๊ฐ๋ค์ ๊ฐ ํด๋นํ๋ ChoiceChip์ผ๋ก ์ ๋ฌ.
- โ
On ChoiceChip Selected: Update Page State
moodKeywordsSelected
-> Set Value toReturn of Func updateMoodKeywordsSelected
- โ
Create CustomFunction
updateMoodKeywordsSelected
- On Chip Select: Add to moodKeywordsSelected
- On Chip Deselect: Remove from moodKeywordsSelected
List<String> updateMoodKeywordsSelected( List<String> moodKeywordsSelected, List<String> choiceChipSelected, List<String> moodKeywordRateOptions, ) { // ๊ธฐ์กด ๋ฆฌ์คํธ๋ฅผ ๋ณต์ฌํ์ฌ ๋ถ๋ณ์ฑ ์ ์ง List<String> updatedList = List.from(moodKeywordsSelected); // 1๏ธโฃ ๊ธฐ์กด ์ ํ๊ฐ ์ค ํด๋น Rate์ ๊ฐ๋ค ์ญ์ updatedList.removeWhere((item) => moodKeywordRateOptions.contains(item)); // 2๏ธโฃ ํ์ฌ ์ ํ๋ ChoiceChip ๊ฐ๋ค์ ์ถ๊ฐ updatedList.addAll(choiceChipSelected); return updatedList; }
- โ
Create CustomFunction
- โ
(์ด์) DiaryPage - AI Comment: ์บ๋ฆญํฐ ์ค์
- diaries DB Field ์ถ๊ฐ: ai_comment_by (Doc Ref: Character)
- DiaryPage - AICommentEditor Component - Return
ai_comment_content
+ai_comment_by
- How? ->
aiCommentPageReturnObject
DataType ์์ฑ
- How? ->
- On ChoiceChipChar Selected: Backend Query Character Doc with same Official_name value.
- โ
(์ด์) HomeFeedPage - FeedCardDiary: AI Comment ์บ๋ฆญํฐ ์ด๋ฏธ์ง ์๋ง๊ฒ ์ ์ฉ
- โ DiaryPage - AI Comment: Save์, ์ฝ๋ฉํธ ์์ฑํ ์บ๋ฆญํฐ Ref๋ Diary์ ์ ์ฅ.
- โ HomeFeedPage - FeedCardDiary - AI Image: Backend Query๋ก ์บ๋ฆญํฐ Doc ๋ถ๋ฌ์์ Image Path ์ง์ .
- โ
(์ด์) HomeFeedPage - FeedCardDiary: Unexpected Null Value Error
- Image Widget์ Path๊ฐ๋ง ๋ฃ์ผ๋ฉด ๋ฐ์ํ๋คโฆ
- ์!!! Default Varilable Value๋ฅผ ๋ฃ์ง ์์๊ธฐ ๋๋ฌธ์ ์๊ธด ์ค๋ฅ์๊ตฌ๋. ๊ฐ๊ณ ์ ํ๊ณ ๋์์ผ ๊นจ๋ฌ์.
- ๐ก ๋ฐฐ์ด ์
- ํญ์ ๋ฐ๋์ Default Value๋ฅผ ๋ฃ๋ ์ต๊ด์ ๋ค์ด์. Unexpected Null Value Error๋ฅผ ๋๋์ฒด ์จ๊ฐ ๊ณณ์์ ๋ช ๋ฒ์ด๋ ๋ณด๋ ๊ฑด์ง.
- Image Widget์ Path๊ฐ๋ง ๋ฃ์ผ๋ฉด ๋ฐ์ํ๋คโฆ
- โ
Deisgn Action chains for
CreateNewChatFromDiary
(Start From: AI Comment ์ฒ๋ฆฌํ ๋ค ๋ค์ด์ด๋ฆฌ ์ ์ฅ๊น์ง ์๋ฃํ ์ํ)- Create Diary
- API Call: createDiarySummary -> Output Var: OutVar1 (๊ฐ๋ช )
- Create New Chat Document
- Create New Message Document: {โroleโ:โdeveloperโ, โcontentโ:โ$systemprompt + $OutVar1โ}
- API Call: createChatFromDiary -> Output Var: OutVar2 (๊ฐ๋ช )
- Create New Message Document: {โroleโ:โassistantโ, โcontentโ: โ$OutVar2โ}
- Navigate To: chatRefParam ์ผ๋ก ํด๋น Chat Document Reference ์ ๋ฌ
๐ฏ ํ ์ผ์ ๋ํ ์์ฝ
-
DiaryPage ๊ฐ์ ํค์๋ ์์คํ
๊ตฌ์ถ
- ChoiceChip ๋ฐ TextField ์ถ๊ฐ
- diaries DB์ ๊ฐ์ ํค์๋ ๊ด๋ จ ํ๋ ์ถ๊ฐ
-
updateMoodKeywordsSelected
ํจ์ ๊ตฌํ
-
AI ์ฝ๋ฉํธ ์บ๋ฆญํฐ ์ค์ ๋ฐ ์ ์ฉ
-
ai_comment_by
ํ๋ ์ถ๊ฐํ์ฌ ์ฝ๋ฉํธ ์บ๋ฆญํฐ ์ ์ฅ - AICommentEditor ์์ ํ์ฌ ์บ๋ฆญํฐ ์ ๋ณด ํฌํจ
- ChoiceChip ์ ํ ์, ํด๋น ์บ๋ฆญํฐ ๋ฐ์ดํฐ๋ฅผ Backend Query๋ก ๋ถ๋ฌ์ค๊ธฐ
-
-
HomeFeedPage AI ์ฝ๋ฉํธ ์ด๋ฏธ์ง ์ค๋ฅ ํด๊ฒฐ
- AI ์ฝ๋ฉํธ ์์ฑ ์ ์บ๋ฆญํฐ ์ฐธ์กฐ๊ฐ ์ ์ฅ
- HomeFeedPage์์ AI ์ฝ๋ฉํธ ์บ๋ฆญํฐ ์ด๋ฏธ์ง ๋ก๋ฉ ๋ฐฉ์ ๊ฐ์
- Unexpected Null Value ์ค๋ฅ ํด๊ฒฐ (๊ธฐ๋ณธ๊ฐ ์ ์ฉ)
๐ฏ ์ถํ์ ํ ์ผ
์์ธํ ๋ณด๋ ค๋ฉด ํด๋ฆญ
-
โ (์ด์) DiaryPage: ๋งํฌ๋ค์ด ๋ทฐ์ด ํ์ฉ (์ค๋ฒํ๋ก์ฐ ๋ฐฉ์ง: Container Height)
-
โ DiaryPage: Mood Slider ๊ฐ์ ๋ฐ๋ผ ์ผ๊ตด ํ์ Emoji ๋ฐ ์๊น ๋ณ๊ฒฝ
- โ Custom Function -
systemPromptTemplate
์ ์ ๋๊ธฐ (๋ฉ์ธ ์์ ์: KSK)- โ ์ถ๊ฐํ ํ๋ผ๋ฏธํฐ ์ ๋ฆฌํ๊ธฐ
- โ Custom Function -
getAIComment
๊ฐ ์ค์ ๋ก ์ ์ฉ ๋๋์ง ํ ์คํธํ๊ธฐ- โ ์ ๋ ฅ๊ฐ์ด ์ ๋ฐ์๋๋์ง ํ์ธ
- โ ์ถ๋ ฅ๊ฐ์ด String์ผ๋ก ์ ์ถ๋ ฅ๋๋์ง ํ์ธ
- โ Chat Page - Create New Chat: ์์คํ
ํ๋กฌํํธ ์ ์ฉํ๊ธฐ
- โถ๏ธ OpenAI API Call ๊ตฌํ: createChatCompletion
- Input: System Prompt(Chat)
- Output: New Chat Message by AI($.choices[0].message.content)
- Additional Actions: Create New Chat, Create New Message
- โถ๏ธ OpenAI API Call ๊ตฌํ: createChatCompletion
- โ DiaryPage - Create New Chat by Diary: ์ผ๊ธฐ์ ๋ด์ฉ์ ๊ธฐ๋ฐ์ผ๋ก, New Chat ์์ฑ
- โ OpenAI API Call ๊ตฌํ: createDiaryComment
- Input: Diary Content, System Prompt(AI Comment)
- Output: AI Comment($.choices[0].message.content)
- โ OpenAI API Call ๊ตฌํ: createDiarySummary
- Input: Diary Content, AI Comment, System Prompt(Diary Summary)
- Output: Diary Summary($.choices[0].message.content)
- โ OpenAI API Call ๊ตฌํ: createChatFromDiary
- Input: Diary Summary, System Prompt(Chat From Diary)
- Output: New Chat Message by AI($.choices[0].message.content)
- Additional Actions: Create New Chat, Create New Message
- โ OpenAI API Call ๊ตฌํ: createDiaryComment
- โ ChatPage - Create New Diary: ๋ํ ๋ด์ฉ์ ๊ธฐ๋ฐ์ผ๋ก, New Diary ์์ฑ
- โ OpenAI API Call ๊ตฌํ: createChatSummary
- Input: Chat Content, System Prompt(Diary From Chat)
- Output: Chat Summary
- โ OpenAI API Call ๊ตฌํ: createDiaryFromChat
- Input: Chat Summary, System Prompt(Diary From Chat)
- Output: New Diary(Title, Content, Mood score)
- โ OpenAI API Call ๊ตฌํ: createChatSummary
-
โ ChatPage: Go to Linked Diary
- โ MoodPage(์๋จ) - Mood Calendar
- โ ๋ ์ง๋ณ๋ก ์์ฑ๋ ๊ฒ์๋ฌผ ์ซ์ ํ์ธ ๊ฐ๋ฅ
- โ ๋ ์ง ํด๋ฆญํ๋ฉด, ํด๋น ๋ ์ง๋ก ์ด๋
- โ MoodPage(ํ๋จ) - Mood stats
- โ ํฌ์ปค์ฑ ๋ ์์ ๊ดํ ํต๊ณ ์๋ฃ ์ถ๋ ฅ
- โ ์ถ๋ ฅ๋ ํต๊ณ ์๋ฃ์ ๋ํ AI์ ์ฝ๋ฉํธ ์ถ๋ ฅ
- โ ํฌ์ปค์ฑ ๋ ์์ ๊ดํ ํต๊ณ ์๋ฃ ์ถ๋ ฅ
- โ HomeFeedPage - flutter_slidable:4.0.0 import ํ ์ ์ฉํ๊ธฐ
-
โ HomeFeedPage: FeedCardDiary์์ ์ข์ฐ slide์ ์ฑํ /ํธ์ง/์ญ์
- โ ChatPage: ์ ์ ๋ํ ์ถ๋ ฅ ๋ด์ฉ์ ์ค๋ฅธ์ชฝ ์ ๋ ฌ
-
โ Chat/Diary: GPT Streaming API
- โ ChatPage - AI ์ ํก ๊ตฌํ (Alarm/Notification)
- ์ฑํ
์์คํ
ํ๋กฌํํธ์ ํต์ฌ์ ๋ฅ๋ํ์ด๋ค.
- ๋ ๋ฆฌ์ผํ๊ฒ ํ๋ ค๋ฉด, create_date of diary/chat ๋ ์ ๋ฌํด์, โ์ด์ โ ๋ฑ ๋ ์ง๋ฅผ ์ธ๊ธํ๋ฉด ์ข์ ๋ฏ.
- Alarm ๊ธฐ๋ฅ ๊ตฌํ ๋ฐฉ๋ฒ ์ฐธ์กฐ
- ์ฑํ
์์คํ
ํ๋กฌํํธ์ ํต์ฌ์ ๋ฅ๋ํ์ด๋ค.
- โ DiaryPage: ์ธ๋ถ ๊ฐ์ ํค์๋ Choice Chips ์ถ๊ฐ ํ DB ์ฐ๋ ์ค์
- โ DiaryPage - AI Comment: Choice chips, mood slider ๋ฑ์ ์
๋ ฅ๊ฐ๋ค์
AI Comment System Prompt
์ ์๋ง๊ฒ ๋ณ๊ฒฝ.- โ **์ด์
์ผ๊ธฐ
๋๋๋ํ ๋ด์ญ
์ ์ฒด (๋๋นต ๊ธฐ์ ๋ถ์ฑ) - โ ์ฌ์ฉ์ ๊ธฐ๋ณธ ์ ๋ณด: ์ด๋ฆ, ์ฑ๋ณ, MBTI, โฆ
- โ ์ธ๋ถ ๊ฐ์ ํค์๋: ์ฆ๊ฑฐ์ด, ์ฌํ, โฆ
- โ ์บ๋ฆญํฐ ์ค์ : ์๋ฏธ, ์ธ๋, ๋ฏผํ
- โ ๊ฐ์ ์์น: 1~100์
- โ ๋ต๋ณ ์์: ์น์ ํ(Healing), ์กฐ์ธํ(Suggestion), ์ ๋ณดํ(Informative)
- โ ๋ต๋ณ ๊ธธ์ด: ์งง๊ฒ, ๋ณดํต, ์์ธํ
- is New Chat
- ํด๋น Chat์ messages๋ ์ฒ์ ์์ฑํ๋ ๊ฑฐ๋๊น, ์ฒซ ์์ฑํ๋ message document์
is_initial = true
๊ฐ ์ค๋ฒ๋ฆฌ๊ณ ๋ชจ๋ ์์คํ ํ๋กฌํํธ ๋ค ๋๋ ค๋ฃ์.- is_initial = false
- ํ๊ณ์ : ๋งจ ์ฒ์ message document์๋ค๊ฐ ์์คํ ํ๋กฌํํธ ๋๋ ค๋ฃ์ผ๋ฉด, ๋ํ ๋์ค ์์ ํ๋ค๊ธด ํ๋ฐ ๊ฐ๋ฅํ์ง. is_initial = true ์ธ ๊ฒ ์๊ณ , ์์ ๋ ๊ฑฐ๋ฉด, ๊ทธ๊ฑฐ ๋คํ๋จผํธ ์ง์ฐ๊ณ ๋ค์ ๋ฃ์ผ๋ฉด ๋์์. ์ด๋ป๊ฒ๋ ๋ชจ๋ฅด๊ฒ ๊ณ .
- ํด๋น Chat์ messages๋ ์ฒ์ ์์ฑํ๋ ๊ฑฐ๋๊น, ์ฒซ ์์ฑํ๋ message document์
- โ **์ด์
- โ DiaryPage - AI Comment: CRUD ์์ฑํ๊ธฐ
- โ tmp_ai_comment field ์์ ๊ณ , doc_ref ํ์ฉ
-
โ DiaryPage - Drawer - ChatHistoryListTile: order by updated_time
-
โ DiaryPage - Interactive Slider import ํ ์ ์ฉ
-
โ HomeFeedPage: Search Diary ๊ธฐ๋ฅ ๊ตฌํ
-
โ AuthPage: Google Login ๊ธฐ๋ฅ ๊ตฌํ
- โ HomeFeedPage - Bottom Sheet (
+
Button): ๋ค์ํ ์ต์ ์ค 1 ์ ํํ ์ ์๋๋ก- ์๋ก์ด ์ผ๊ธฐ: Go to DiaryPage
- ๊ฐ์ ๊ธฐ๋ก: Go to MoodPage
- โ MoodPage(ํ์
): Mood ์ค์ ์ฌ๋ผ์ด๋ CRUD
- Create
- Read
- Update
- Delete
- โ HomeFeedPage - ListView - FeedCardMood ํ์
-
โ HomeFeedPage - ListView: FeedCardDiary, FeedCardMood, FeedCardChat ์ปดํฌ๋ํธ ์๊ฐ์ ์ ๋ ฌ (Cloud Function ํ์ฉ)
-
โ HomeFeedPage - DiaryPage ์ฌ์ด์ MoodEditPage ์ ์: MoodSlider, MoodKeywordsRate(5~1), MoodDescription ์์ ฏ ๋ฑ ์ฎ๊ธฐ๊ธฐ
- โ
2025.2.5 ์
๊น์ง ๋ฐํ์ฉ ์ต์ข ๋ฒ์ APK ์ถ์ถ ๋ฐ ์ค์น
๐ญ ์ผ๊ธฐ
๋ฌด์ํ ๋๋นต์ง๋ก ์ธํด์ ๊ธฐ์ ๋ถ์ฑ๊ฐ ๋ฌด๋ญ๋ฌด๋ญ ์์ด๋ ๊ฒ ๋๊ปด์ง๋คใ ใ ์ ์ถ ๋ง๊ฐ์ผ์ด 3์ผ ๋จ์์ผ๋๊น ๋ญโฆใ
โจ GPT์ ์ฝ๋ฉํธ (KPT)
โ ์ํ ์ (Keep)
- ๐ฏ ๊ฐ์ ํค์๋ ์์คํ ๊ตฌ์ถ: ์ฌ์ฉ์๊ฐ ๊ฐ์ ์ ์ง๊ด์ ์ผ๋ก ๊ธฐ๋กํ ์ ์๋๋ก ChoiceChip์ ์ ์ฉํ ์ ์ด ์ข์!
- ๐ค AI ์ฝ๋ฉํธ ์บ๋ฆญํฐ ์ ์ฉ: ์บ๋ฆญํฐ๋ณ ๋ฐ์์ ์ค์ ํ์ฌ ๋ชฐ์ ๊ฐ์ ๋์ธ ์ ์ด ์ธ์์ ์ด์ผ.
- ๐ HomeFeedPage ์ค๋ฅ ํด๊ฒฐ: ๊ธฐ๋ณธ๊ฐ์ ์ค์ ํ์ฌ Unexpected Null Value ์ค๋ฅ๋ฅผ ๋ฐฉ์งํ ์ ์ด ํ๋ฅญํด!
โ ์์ฌ์ด ์ (Problem)
- โณ ์์๋ณด๋ค ๊ธด ๊ฐ๋ฐ ์๊ฐ: ๊ฐ์ ํค์๋์ AI ์ฝ๋ฉํธ ๊ธฐ๋ฅ ๊ตฌํ์ ์๊ฐ์ด ์์๋ณด๋ค ๋ง์ด ์์๋จ.
- ๐ ์บ๋ฆญํฐ ๋ฐ์ดํฐ ๋ณต์ก์ฑ ์ฆ๊ฐ: ๋ฐ์ดํฐ ํ๋ฆ์ด ๋ณต์กํด์ ธ ์ ์ง๋ณด์๊ฐ ์ด๋ ค์ธ ๊ฐ๋ฅ์ฑ์ด ์์.
- ๐ ๋ฌธ์ ํด๊ฒฐ ๊ณผ์ ๊ธฐ๋ก ๋ถ์กฑ: ์ค๋ฅ ํด๊ฒฐ ๊ณผ์ ์ ์ ๋ฆฌํ์ง ์์ ๊ฐ์ ๋ฌธ์ ๋ฐ์ ์ ์๊ฐ ๋ญ๋น ๊ฐ๋ฅ.
๐ ์๋ํด๋ณผ ์ (Try)
- ๐ ๊ธฐ๋ฅ๋ณ ๊ฐ๋ฐ ์๊ฐ ์กฐ์ : ์์๋ณด๋ค ์ค๋ ๊ฑธ๋ฆฌ๋ ์์ ์ ๋ฏธ๋ฆฌ ํ์ ํ๊ณ ์ผ์ ์กฐ์ ํ์.
- ๐ ๋ฐ์ดํฐ ํ๋ฆ ์๊ฐํ: ์บ๋ฆญํฐ ์ค์ ๊ณผ ๊ด๋ จ๋ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ๋ค์ด์ด๊ทธ๋จ์ผ๋ก ์ ๋ฆฌํด๋ณด๊ธฐ.
- ๐ ๋ฌธ์ ํด๊ฒฐ ๊ณผ์ ์ ๋ฆฌ ์ต๊ดํ: ํด๊ฒฐํ ์ด์๋ฅผ ๋ฌธ์ํํ์ฌ ์ฌ๋ฐ ๋ฐฉ์ง ์ ๋ต ๋ง๋ จ.
๐ ๊ฒฐ๋ก
์ค๋์ ๊ฐ์ ํค์๋ ์์คํ ์ ๊ตฌ์ถํ๊ณ , AI ์ฝ๋ฉํธ์ ์บ๋ฆญํฐ ์ค์ ์ ์ ์ฉํ ํ๋ฃจ์์ด. ์ค๋ฅ ํด๊ฒฐ์ ํตํด ๊ธฐ๋ณธ๊ฐ ์ค์ ์ ์ค์์ฑ์ ๋ค์ ํ์ธํ๊ณ , ์์ผ๋ก ๊ฐ๋ฐ ์๊ฐ์ ๋ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๊ฒ์ด ํ์ํ ๊ฒ ๊ฐ์! ๐๐ฅ
๋๊ธ ๋จ๊ธฐ๊ธฐ