102 lines
2.7 KiB
TypeScript
102 lines
2.7 KiB
TypeScript
/**
|
|
* OpenAI API 유틸리티
|
|
*/
|
|
|
|
const OPENAI_API_URL = 'https://api.openai.com/v1/chat/completions'
|
|
|
|
interface ChatMessage {
|
|
role: 'system' | 'user' | 'assistant'
|
|
content: string
|
|
}
|
|
|
|
interface OpenAIResponse {
|
|
choices: {
|
|
message: {
|
|
content: string
|
|
}
|
|
}[]
|
|
}
|
|
|
|
export async function callOpenAI(messages: ChatMessage[], jsonMode = true): Promise<string> {
|
|
const apiKey = process.env.OPENAI_API_KEY
|
|
|
|
if (!apiKey || apiKey === 'your-openai-api-key-here') {
|
|
throw new Error('OPENAI_API_KEY가 설정되지 않았습니다.')
|
|
}
|
|
|
|
const response = await fetch(OPENAI_API_URL, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Bearer ${apiKey}`
|
|
},
|
|
body: JSON.stringify({
|
|
model: 'gpt-4o-mini',
|
|
messages,
|
|
temperature: 0.1,
|
|
...(jsonMode && { response_format: { type: 'json_object' } })
|
|
})
|
|
})
|
|
|
|
if (!response.ok) {
|
|
const error = await response.text()
|
|
throw new Error(`OpenAI API 오류: ${response.status} - ${error}`)
|
|
}
|
|
|
|
const data = await response.json() as OpenAIResponse
|
|
return data.choices[0].message.content
|
|
}
|
|
|
|
/**
|
|
* 주간보고 텍스트 분석 프롬프트
|
|
*/
|
|
export function buildParseReportPrompt(rawText: string): ChatMessage[] {
|
|
return [
|
|
{
|
|
role: 'system',
|
|
content: `당신은 주간업무보고 텍스트를 분석하여 구조화된 JSON으로 변환하는 전문가입니다.
|
|
|
|
입력된 텍스트에서 다음 정보를 추출하세요:
|
|
1. 직원 정보 (이름, 이메일)
|
|
2. 프로젝트별 실적 (프로젝트명, 금주실적, 차주계획)
|
|
3. 공통사항 (이슈/리스크, 휴가일정, 기타사항)
|
|
4. 보고 주차 정보 (텍스트에서 날짜나 주차 정보 추출)
|
|
|
|
반드시 아래 JSON 형식으로 응답하세요:
|
|
{
|
|
"reportYear": 2025,
|
|
"reportWeek": 1,
|
|
"weekStartDate": "2025-01-06",
|
|
"weekEndDate": "2025-01-10",
|
|
"reports": [
|
|
{
|
|
"employeeName": "홍길동",
|
|
"employeeEmail": "hong@example.com",
|
|
"projects": [
|
|
{
|
|
"projectName": "프로젝트명",
|
|
"workDescription": "금주 실적 내용",
|
|
"planDescription": "차주 계획 내용"
|
|
}
|
|
],
|
|
"issueDescription": "이슈/리스크 내용 또는 null",
|
|
"vacationDescription": "휴가 일정 또는 null",
|
|
"remarkDescription": "기타 사항 또는 null"
|
|
}
|
|
]
|
|
}
|
|
|
|
주의사항:
|
|
- 이메일이 없으면 employeeEmail은 null로
|
|
- 프로젝트가 여러개면 projects 배열에 모두 포함
|
|
- 날짜 형식은 YYYY-MM-DD
|
|
- 주차 정보가 없으면 현재 날짜 기준으로 추정
|
|
- 실적/계획이 명확히 구분 안되면 workDescription에 통합`
|
|
},
|
|
{
|
|
role: 'user',
|
|
content: rawText
|
|
}
|
|
]
|
|
}
|