Files
weeklyreport/backend/api/meeting/[id]/analyze.post.ts
2026-01-11 14:02:28 +09:00

106 lines
3.2 KiB
TypeScript

import { queryOne, execute } from '../../../utils/db'
import { requireAuth } from '../../../utils/session'
import { callOpenAI } from '../../../utils/openai'
/**
* 회의록 AI 분석
* POST /api/meeting/[id]/analyze
*/
export default defineEventHandler(async (event) => {
await requireAuth(event)
const meetingId = parseInt(event.context.params?.id || '0')
if (!meetingId) {
throw createError({ statusCode: 400, message: '회의록 ID가 필요합니다.' })
}
// 회의록 조회
const meeting = await queryOne<any>(`
SELECT m.*, p.project_name
FROM wr_meeting m
LEFT JOIN wr_project_info p ON m.project_id = p.project_id
WHERE m.meeting_id = $1
`, [meetingId])
if (!meeting) {
throw createError({ statusCode: 404, message: '회의록을 찾을 수 없습니다.' })
}
if (!meeting.raw_content) {
throw createError({ statusCode: 400, message: '분석할 회의 내용이 없습니다.' })
}
// AI 프롬프트
const systemPrompt = `당신은 회의록 정리 전문가입니다.
아래 회의 내용을 분석하여 JSON 형식으로 정리해주세요.
## 출력 형식 (JSON만 출력, 다른 텍스트 없이)
{
"agendas": [
{
"no": 1,
"title": "안건 제목",
"content": "상세 내용 요약",
"status": "DECIDED | PENDING | IN_PROGRESS",
"decision": "결정 내용 (결정된 경우만)",
"todos": [
{
"title": "TODO 제목",
"assignee": "담당자명 또는 null",
"reason": "TODO로 추출한 이유"
}
]
}
],
"summary": "전체 회의 요약 (2-3문장)"
}
## 규칙
1. 안건은 주제별로 분리하여 넘버링
2. 결정된 사항은 DECIDED, 추후 논의는 PENDING, 진행중은 IN_PROGRESS
3. 미결정/진행중 사항 중 액션이 필요한 것은 todos로 추출
4. 담당자가 언급되면 assignee에 기록 (없으면 null)
5. JSON 외 다른 텍스트 출력 금지`
const userPrompt = `## 회의 정보
- 제목: ${meeting.meeting_title}
- 프로젝트: ${meeting.project_name || '없음 (내부업무)'}
- 일자: ${meeting.meeting_date}
## 회의 내용
${meeting.raw_content}`
try {
const result = await callOpenAI([
{ role: 'system', content: systemPrompt },
{ role: 'user', content: userPrompt }
], true, 'gpt-4o-mini')
// JSON 파싱
let aiResult: any
try {
// JSON 블록 추출 (```json ... ``` 형태 처리)
let jsonStr = result.trim()
if (jsonStr.startsWith('```')) {
jsonStr = jsonStr.replace(/^```json?\n?/, '').replace(/\n?```$/, '')
}
aiResult = JSON.parse(jsonStr)
} catch (e) {
console.error('AI result parse error:', result)
throw createError({ statusCode: 500, message: 'AI 응답 파싱 실패' })
}
// DB 저장
await execute(`
UPDATE wr_meeting
SET ai_summary = $1, ai_status = 'PENDING', ai_processed_at = NOW()
WHERE meeting_id = $2
`, [JSON.stringify(aiResult), meetingId])
return { success: true, result: aiResult }
} catch (e: any) {
console.error('AI analyze error:', e)
throw createError({ statusCode: 500, message: e.message || 'AI 분석 실패' })
}
})