Skip to content

Cha 3 answer feedback#21

Open
Junseong0829 wants to merge 6 commits into
mainfrom
cha-3-answer-feedback
Open

Cha 3 answer feedback#21
Junseong0829 wants to merge 6 commits into
mainfrom
cha-3-answer-feedback

Conversation

@Junseong0829

@Junseong0829 Junseong0829 commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

개요

답변 생성 완료 후 피드백(👍/👎) 버튼을 표시하고, 부정 피드백 시 답변을 1회 재생성하는 기능을 추가합니다.

주요 변경사항

  • 피드백 버튼: 답변 완료 후 말풍선 아래에 👍/👎 아이콘 표시. 평소엔 회색으로 가시성을 해치지 않고, 선택 시 primary 색상으로 강조. 옆에 "답변이 도움이 되었나요?" 안내 문구 표시 (피드백 후 사라짐)
  • 👍 (도움됨): PUT /v1/widget/messages/:id/feedback 로 GOOD 저장
  • 👎 (도움 안 됨): BAD 저장 후 POST /v1/widget/messages/:id/regenerate/stream 로 답변 1회 재생성. 원본 답변은 제거되고 같은 자리에서 재생성 답변이 스트리밍되며, 완료 후 "다시 생성된 답변" 라벨 표시
  • 재생성된 답변에도 피드백 가능하나 재재생성은 불가 (백엔드 1회 제한과 일치)
  • 재생성 실패 시 원본 답변 복원 및 👎 재클릭으로 재시도 가능
  • SSE 스트림이 메시지 ID를 내려주지 않으므로, 스트림 완료 직후 GET /v1/widget/messages?limit=1 로 서버 메시지 ID를 조회해 연결

Summary by CodeRabbit

  • 신규 기능
    • 채팅 위젯에 답변 피드백(좋아요/별로예요) 버튼과 BAD 1회 재생성 흐름을 추가했습니다.
    • 재생성 및 스트리밍 응답 완료 후, 답변과 출처(sources) 정보가 함께 갱신됩니다.
  • 버그 수정
    • 스트리밍 중단(Abort)·타임아웃·서버 이벤트 파싱을 안정화해 응답 생성이 더 일관되게 동작합니다.
    • 재생성 실패/중단 시 입력 및 기존 답변 상태가 덜 깨지도록 보완했습니다.
  • 기타
    • 피드백 아이콘과 관련 UI 라벨링이 개선되어 표시 정합성이 향상되었습니다.

@Junseong0829 Junseong0829 requested a review from no-ikjun July 9, 2026 22:10
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

위젯 메시지와 피드백 응답 타입을 추가하고, 공통 스트리밍 헬퍼를 기반으로 답변 재생성·피드백 제출·최신 assistant 메시지 조회 API를 구현했습니다. ChatWidget에는 피드백 버튼과 BAD 답변 1회 재생성 흐름이 연결되었습니다.

Changes

위젯 피드백 흐름

Layer / File(s) Summary
메시지 및 피드백 계약
src/api/types.ts, src/widget/types.ts
피드백 평점, 서버 메시지 ID, 피드백 상태, 재생성 여부와 위젯 메시지·페이지네이션 응답 타입을 추가했습니다.
스트리밍 및 피드백 API
src/api/widgetChat.ts
SSE 스트리밍 처리를 공통 헬퍼로 분리하고, AbortSignal·타임아웃·리소스 정규화를 유지하면서 답변 재생성, 피드백 제출, 최신 assistant 메시지 조회 API를 추가했습니다.
위젯 피드백 및 재생성 UI
src/components/Icons.tsx, src/widget/ChatWidget.tsx
좋아요·싫어요 버튼을 추가하고, 서버 메시지 ID 연결, 피드백 중복 방지, BAD 피드백 후 스트리밍 재생성 및 결과 복원·렌더링을 구현했습니다.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ChatWidget
  participant widgetApiClient
  participant streamWidgetChatResponse
  ChatWidget->>widgetApiClient: 피드백 제출
  widgetApiClient-->>ChatWidget: 피드백 응답
  ChatWidget->>streamWidgetChatResponse: BAD 답변 재생성 요청
  streamWidgetChatResponse->>widgetApiClient: 재생성 SSE 요청
  widgetApiClient-->>streamWidgetChatResponse: 답변 청크와 resources 이벤트
  streamWidgetChatResponse-->>ChatWidget: 재생성 답변과 sources 반영
Loading

Possibly related PRs

Poem

깡충 뛰는 토끼가 엄지를 들고,
싫은 답엔 새 답을 다시 빚어요.
청크는 졸졸, 출처는 반짝,
피드백 버튼도 나란히 웃고,
더 좋은 답이 당근처럼 자라요! 🐰

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 답변 피드백 추가라는 변경의 핵심을 직접 가리켜 PR 내용과 관련이 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cha-3-answer-feedback

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/widget/types.ts (1)

13-13: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

FeedbackRating 중복 정의 — 단일 출처로 통합 권장.

동일한 FeedbackRatingsrc/api/types.ts:112에도 정의되어 있습니다. 두 정의가 같은 계약을 표현하므로, 한쪽만 값이 바뀌면(예: 등급 추가) 조용히 불일치가 생길 수 있습니다. src/api/types.ts의 정의를 재-export 하는 방식으로 통합하는 것을 고려해 주세요.

♻️ 통합 예시
-export type FeedbackRating = "GOOD" | "BAD";
+export type { FeedbackRating } from "../api/types";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/widget/types.ts` at line 13, `FeedbackRating` is defined in both
`src/widget/types.ts` and `src/api/types.ts`, creating duplicated contract
source. Update the widget types to reuse the API type instead of redefining the
union, and keep the symbol `FeedbackRating` available via re-export/import from
the shared API types module so there is a single source of truth for future
rating changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/widget/types.ts`:
- Line 13: `FeedbackRating` is defined in both `src/widget/types.ts` and
`src/api/types.ts`, creating duplicated contract source. Update the widget types
to reuse the API type instead of redefining the union, and keep the symbol
`FeedbackRating` available via re-export/import from the shared API types module
so there is a single source of truth for future rating changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0ee92a8f-7426-4ea5-820c-f6e8a54c44c4

📥 Commits

Reviewing files that changed from the base of the PR and between fe97d21 and 21614da.

📒 Files selected for processing (5)
  • src/api/types.ts
  • src/api/widgetChat.ts
  • src/components/Icons.tsx
  • src/widget/ChatWidget.tsx
  • src/widget/types.ts

@no-ikjun no-ikjun left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Junseong0829

Image

문제

  • 다른 질문을 한 이후에, 예전 답변에 대한 재생성 요청을 할 경우 가장 최근에 입력한 프롬프트로 넘어감.

추천 해결법

  • 다른 답변이 이미 생겼을 경우 이전 답변에 반응을 눌러도 답변 재생성으로 넘어가지 않도록 막기

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 9, 2026

Copy link
Copy Markdown

Deploying chatbot-fe with  Cloudflare Pages  Cloudflare Pages

Latest commit: c315aba
Status: ✅  Deploy successful!
Preview URL: https://b415dc70.chatbot-fe-bmx.pages.dev
Branch Preview URL: https://cha-3-answer-feedback.chatbot-fe-bmx.pages.dev

View logs

@no-ikjun

no-ikjun commented Jul 9, 2026

Copy link
Copy Markdown
Member

@Junseong0829

지금은 아예 반응 버튼이 비활성화되는데, 재생성만 막는 방식으로 재구현

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/widget/ChatWidget.tsx (2)

471-479: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

재생성 실패 복원 시 로컬 피드백이 서버 상태와 어긋납니다.

handleFeedback에서 submitMessageFeedback(BAD)가 이미 성공한 뒤 regenerateAnswer(msg)가 호출되는데, originalMsg는 렌더 시점 스냅샷이라 feedback이 갱신 이전 값(예: undefined)입니다. 여기서 { ...originalMsg }로 복원하면 서버에는 BAD가 저장돼 있는데 로컬은 피드백이 초기화되어 "답변이 도움이 되었나요?" 문구가 다시 노출됩니다. 복원 시 BAD 선택 상태를 유지해도 재시도 흐름(👎 재클릭 → 재생성)은 그대로 동작합니다.

🔧 제안 수정
         return prev.map((msg) =>
-          msg.id === regenMsgId ? { ...originalMsg } : msg,
+          msg.id === regenMsgId ? { ...originalMsg, feedback: "BAD" } : msg,
         );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/widget/ChatWidget.tsx` around lines 471 - 479, 재생성 실패 복원 시 최신 BAD 피드백 상태를
유지하도록 수정하세요. handleFeedback에서 submitMessageFeedback(BAD) 성공 후 regenerateAnswer가
호출되는 흐름과 setMessages 내부의 originalMsg 복원 로직을 확인하고, { ...originalMsg } 대신 해당 메시지의
기존 최신 feedback을 보존하거나 BAD로 명시해 복원하세요.

379-397: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

attachServerId가 최신 assistant 메시지를 현재 답변으로 가정합니다.
fetchLatestAssistantMessage()limit=1 결과를 그대로 쓰기 때문에, 같은 세션에서 연속 전송되거나 다른 탭에서 메시지가 먼저 저장되면 다른 답변의 serverId가 붙을 수 있습니다. 서버 응답의 메시지 ID를 onComplete에서 직접 돌려주거나, 생성 시점의 로컬 ID와 1:1로 매핑할 수 있게 바꾸는 쪽이 안전합니다.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/widget/ChatWidget.tsx` around lines 379 - 397, attachServerId currently
assigns the latest assistant message indiscriminately, which can attach another
response’s serverId during concurrent or cross-tab sends. Update the completion
flow around attachServerId and onComplete to use the server message ID returned
by the server directly, or establish an explicit one-to-one mapping from the
localId to the created server message; remove reliance on
fetchLatestAssistantMessage’s limit=1 result.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/widget/ChatWidget.tsx`:
- Around line 471-479: 재생성 실패 복원 시 최신 BAD 피드백 상태를 유지하도록 수정하세요. handleFeedback에서
submitMessageFeedback(BAD) 성공 후 regenerateAnswer가 호출되는 흐름과 setMessages 내부의
originalMsg 복원 로직을 확인하고, { ...originalMsg } 대신 해당 메시지의 기존 최신 feedback을 보존하거나
BAD로 명시해 복원하세요.
- Around line 379-397: attachServerId currently assigns the latest assistant
message indiscriminately, which can attach another response’s serverId during
concurrent or cross-tab sends. Update the completion flow around attachServerId
and onComplete to use the server message ID returned by the server directly, or
establish an explicit one-to-one mapping from the localId to the created server
message; remove reliance on fetchLatestAssistantMessage’s limit=1 result.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2abf0fee-cab9-4d93-a5ac-853798807a5f

📥 Commits

Reviewing files that changed from the base of the PR and between 1ac7e1a and c315aba.

📒 Files selected for processing (1)
  • src/widget/ChatWidget.tsx

@no-ikjun

Copy link
Copy Markdown
Member

@Junseong0829

  • 이전 답변 반응 눌렀을 때 맨 아래로 스크롤 되는 버그 수정 부탁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants