853 lines
28 KiB
Python
853 lines
28 KiB
Python
import random
|
|
from typing import List
|
|
|
|
from fastapi import Request, status
|
|
from fastapi.exceptions import HTTPException
|
|
from sqlalchemy import Connection, text
|
|
from sqlalchemy.exc import SQLAlchemyError
|
|
|
|
from app.lyrics.schemas.lyrics_schema import (
|
|
AttributeData,
|
|
PromptTemplateData,
|
|
SongFormData,
|
|
SongSampleData,
|
|
StoreData,
|
|
)
|
|
from app.utils.chatgpt_prompt import chatgpt_api
|
|
|
|
|
|
async def get_store_info(conn: Connection) -> List[StoreData]:
|
|
try:
|
|
query = """SELECT * FROM store_default_info;"""
|
|
result = await conn.execute(text(query))
|
|
|
|
all_store_info = [
|
|
StoreData(
|
|
id=row[0],
|
|
store_info=row[1],
|
|
store_name=row[2],
|
|
store_category=row[3],
|
|
store_region=row[4],
|
|
store_address=row[5],
|
|
store_phone_number=row[6],
|
|
created_at=row[7],
|
|
)
|
|
for row in result
|
|
]
|
|
|
|
result.close()
|
|
return all_store_info
|
|
except SQLAlchemyError as e:
|
|
print(e)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="요청하신 서비스가 잠시 내부적으로 문제가 발생하였습니다.",
|
|
)
|
|
except Exception as e:
|
|
print(e)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="알수없는 이유로 서비스 오류가 발생하였습니다",
|
|
)
|
|
|
|
|
|
async def get_attribute(conn: Connection) -> List[AttributeData]:
|
|
try:
|
|
query = """SELECT * FROM attribute;"""
|
|
result = await conn.execute(text(query))
|
|
|
|
all_attribute = [
|
|
AttributeData(
|
|
id=row[0],
|
|
attr_category=row[1],
|
|
attr_value=row[2],
|
|
created_at=row[3],
|
|
)
|
|
for row in result
|
|
]
|
|
|
|
result.close()
|
|
return all_attribute
|
|
except SQLAlchemyError as e:
|
|
print(e)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="요청하신 서비스가 잠시 내부적으로 문제가 발생하였습니다.",
|
|
)
|
|
except Exception as e:
|
|
print(e)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="알수없는 이유로 서비스 오류가 발생하였습니다",
|
|
)
|
|
|
|
|
|
async def get_attribute(conn: Connection) -> List[AttributeData]:
|
|
try:
|
|
query = """SELECT * FROM attribute;"""
|
|
result = await conn.execute(text(query))
|
|
|
|
all_attribute = [
|
|
AttributeData(
|
|
id=row[0],
|
|
attr_category=row[1],
|
|
attr_value=row[2],
|
|
created_at=row[3],
|
|
)
|
|
for row in result
|
|
]
|
|
|
|
result.close()
|
|
return all_attribute
|
|
except SQLAlchemyError as e:
|
|
print(e)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="요청하신 서비스가 잠시 내부적으로 문제가 발생하였습니다.",
|
|
)
|
|
except Exception as e:
|
|
print(e)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="알수없는 이유로 서비스 오류가 발생하였습니다",
|
|
)
|
|
|
|
|
|
async def get_sample_song(conn: Connection) -> List[SongSampleData]:
|
|
try:
|
|
query = """SELECT * FROM song_sample;"""
|
|
result = await conn.execute(text(query))
|
|
|
|
all_sample_song = [
|
|
SongSampleData(
|
|
id=row[0],
|
|
ai=row[1],
|
|
ai_model=row[2],
|
|
genre=row[3],
|
|
sample_song=row[4],
|
|
)
|
|
for row in result
|
|
]
|
|
|
|
result.close()
|
|
return all_sample_song
|
|
except SQLAlchemyError as e:
|
|
print(e)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="요청하신 서비스가 잠시 내부적으로 문제가 발생하였습니다.",
|
|
)
|
|
except Exception as e:
|
|
print(e)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="알수없는 이유로 서비스 오류가 발생하였습니다",
|
|
)
|
|
|
|
|
|
async def get_prompt_template(conn: Connection) -> List[PromptTemplateData]:
|
|
try:
|
|
query = """SELECT * FROM prompt_template;"""
|
|
result = await conn.execute(text(query))
|
|
|
|
all_prompt_template = [
|
|
PromptTemplateData(
|
|
id=row[0],
|
|
description=row[1],
|
|
prompt=row[2],
|
|
)
|
|
for row in result
|
|
]
|
|
|
|
result.close()
|
|
return all_prompt_template
|
|
except SQLAlchemyError as e:
|
|
print(e)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="요청하신 서비스가 잠시 내부적으로 문제가 발생하였습니다.",
|
|
)
|
|
except Exception as e:
|
|
print(e)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="알수없는 이유로 서비스 오류가 발생하였습니다",
|
|
)
|
|
|
|
|
|
async def get_song_result(conn: Connection) -> List[PromptTemplateData]:
|
|
try:
|
|
query = """SELECT * FROM prompt_template;"""
|
|
result = await conn.execute(text(query))
|
|
|
|
all_prompt_template = [
|
|
PromptTemplateData(
|
|
id=row[0],
|
|
description=row[1],
|
|
prompt=row[2],
|
|
)
|
|
for row in result
|
|
]
|
|
|
|
result.close()
|
|
return all_prompt_template
|
|
except SQLAlchemyError as e:
|
|
print(e)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="요청하신 서비스가 잠시 내부적으로 문제가 발생하였습니다.",
|
|
)
|
|
except Exception as e:
|
|
print(e)
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="알수없는 이유로 서비스 오류가 발생하였습니다",
|
|
)
|
|
|
|
|
|
async def make_song_result(request: Request, conn: Connection):
|
|
try:
|
|
# 1. Form 데이터 파싱
|
|
form_data = await SongFormData.from_form(request)
|
|
|
|
print(f"\n{'=' * 60}")
|
|
print(f"Store ID: {form_data.store_id}")
|
|
print(f"Lyrics IDs: {form_data.lyrics_ids}")
|
|
print(f"Prompt IDs: {form_data.prompts}")
|
|
print(f"{'=' * 60}\n")
|
|
|
|
# 2. Store 정보 조회
|
|
store_query = """
|
|
SELECT * FROM store_default_info WHERE id=:id;
|
|
"""
|
|
store_result = await conn.execute(text(store_query), {"id": form_data.store_id})
|
|
|
|
all_store_info = [
|
|
StoreData(
|
|
id=row[0],
|
|
store_info=row[1],
|
|
store_name=row[2],
|
|
store_category=row[3],
|
|
store_region=row[4],
|
|
store_address=row[5],
|
|
store_phone_number=row[6],
|
|
created_at=row[7],
|
|
)
|
|
for row in store_result
|
|
]
|
|
|
|
if not all_store_info:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Store not found: {form_data.store_id}",
|
|
)
|
|
|
|
store_info = all_store_info[0]
|
|
print(f"Store: {store_info.store_name}")
|
|
|
|
# 3. 속성 조회 -- 단계별 선택 프로세서시 구현 필요 없음
|
|
|
|
# 4. Sample Song 조회 및 결합
|
|
combined_sample_song = None
|
|
|
|
if form_data.lyrics_ids:
|
|
print(f"\n[샘플 가사 조회] - {len(form_data.lyrics_ids)}개")
|
|
|
|
lyrics_query = """
|
|
SELECT sample_song FROM song_sample
|
|
WHERE id IN :ids
|
|
ORDER BY created_at;
|
|
"""
|
|
lyrics_result = await conn.execute(
|
|
text(lyrics_query), {"ids": tuple(form_data.lyrics_ids)}
|
|
)
|
|
|
|
sample_songs = [
|
|
row.sample_song for row in lyrics_result.fetchall() if row.sample_song
|
|
]
|
|
|
|
if sample_songs:
|
|
combined_sample_song = "\n\n".join(
|
|
[f"[샘플 {i + 1}]\n{song}" for i, song in enumerate(sample_songs)]
|
|
)
|
|
print(f"{len(sample_songs)}개의 샘플 가사 조회 완료")
|
|
else:
|
|
print("샘플 가사가 비어있습니다")
|
|
else:
|
|
print("선택된 lyrics가 없습니다")
|
|
|
|
# 5. 템플릿 가져오기
|
|
if not form_data.prompts:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
|
detail="프롬프트 ID가 필요합니다",
|
|
)
|
|
|
|
print("템플릿 가져오기")
|
|
|
|
prompts_query = """
|
|
SELECT * FROM prompt_template WHERE id=:id;
|
|
"""
|
|
|
|
# ✅ 수정: store_query → prompts_query
|
|
prompts_result = await conn.execute(
|
|
text(prompts_query), {"id": form_data.prompts}
|
|
)
|
|
|
|
prompts_info = [
|
|
PromptTemplateData(
|
|
id=row[0],
|
|
description=row[1],
|
|
prompt=row[2],
|
|
)
|
|
for row in prompts_result
|
|
]
|
|
|
|
if not prompts_info:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Prompt not found: {form_data.prompts}",
|
|
)
|
|
|
|
prompt = prompts_info[0]
|
|
print(f"Prompt Template: {prompt.prompt}")
|
|
|
|
# ✅ 6. 프롬프트 조합
|
|
updated_prompt = prompt.prompt.replace("###", form_data.attributes_str).format(
|
|
name=store_info.store_name or "",
|
|
address=store_info.store_address or "",
|
|
category=store_info.store_category or "",
|
|
description=store_info.store_info or "",
|
|
)
|
|
|
|
updated_prompt += f"""
|
|
|
|
다음은 참고해야 하는 샘플 가사 정보입니다.
|
|
|
|
샘플 가사를 참고하여 작곡을 해주세요.
|
|
|
|
{combined_sample_song}
|
|
"""
|
|
|
|
print(f"\n[업데이트된 프롬프트]\n{updated_prompt}\n")
|
|
|
|
# 7. 모델에게 요청
|
|
generated_lyrics = await chatgpt_api.generate_lyrics(prompt=updated_prompt)
|
|
|
|
# 글자 수 계산
|
|
total_chars_with_space = len(generated_lyrics)
|
|
total_chars_without_space = len(
|
|
generated_lyrics.replace(" ", "")
|
|
.replace("\n", "")
|
|
.replace("\r", "")
|
|
.replace("\t", "")
|
|
)
|
|
|
|
# final_lyrics 생성
|
|
final_lyrics = f"""속성 {form_data.attributes_str}
|
|
전체 글자 수 (공백 포함): {total_chars_with_space}자
|
|
전체 글자 수 (공백 제외): {total_chars_without_space}자\r\n\r\n{generated_lyrics}"""
|
|
|
|
print("=" * 40)
|
|
print("[translate:form_data.attributes_str:] ", form_data.attributes_str)
|
|
print("[translate:total_chars_with_space:] ", total_chars_with_space)
|
|
print("[translate:total_chars_without_space:] ", total_chars_without_space)
|
|
print("[translate:final_lyrics:]")
|
|
print(final_lyrics)
|
|
print("=" * 40)
|
|
|
|
# 8. DB 저장
|
|
insert_query = """
|
|
INSERT INTO song_results_all (
|
|
store_info, store_name, store_category, store_address, store_phone_number,
|
|
description, prompt, attr_category, attr_value,
|
|
ai, ai_model, genre,
|
|
sample_song, result_song, created_at
|
|
) VALUES (
|
|
:store_info, :store_name, :store_category, :store_address, :store_phone_number,
|
|
:description, :prompt, :attr_category, :attr_value,
|
|
:ai, :ai_model, :genre,
|
|
:sample_song, :result_song, NOW()
|
|
);
|
|
"""
|
|
|
|
# ✅ attr_category, attr_value 추가
|
|
insert_params = {
|
|
"store_info": store_info.store_info or "",
|
|
"store_name": store_info.store_name,
|
|
"store_category": store_info.store_category or "",
|
|
"store_address": store_info.store_address or "",
|
|
"store_phone_number": store_info.store_phone_number or "",
|
|
"description": store_info.store_info or "",
|
|
"prompt": form_data.prompts,
|
|
"attr_category": ", ".join(form_data.attributes.keys())
|
|
if form_data.attributes
|
|
else "",
|
|
"attr_value": ", ".join(form_data.attributes.values())
|
|
if form_data.attributes
|
|
else "",
|
|
"ai": "ChatGPT",
|
|
"ai_model": form_data.llm_model,
|
|
"genre": "후크송",
|
|
"sample_song": combined_sample_song or "없음",
|
|
"result_song": final_lyrics,
|
|
}
|
|
|
|
await conn.execute(text(insert_query), insert_params)
|
|
await conn.commit()
|
|
|
|
print("결과 저장 완료")
|
|
|
|
print("\n전체 결과 조회 중...")
|
|
|
|
# 9. 생성 결과 가져오기 (created_at 역순)
|
|
select_query = """
|
|
SELECT * FROM song_results_all
|
|
ORDER BY created_at DESC;
|
|
"""
|
|
|
|
all_results = await conn.execute(text(select_query))
|
|
|
|
results_list = [
|
|
{
|
|
"id": row.id,
|
|
"store_info": row.store_info,
|
|
"store_name": row.store_name,
|
|
"store_category": row.store_category,
|
|
"store_address": row.store_address,
|
|
"store_phone_number": row.store_phone_number,
|
|
"description": row.description,
|
|
"prompt": row.prompt,
|
|
"attr_category": row.attr_category,
|
|
"attr_value": row.attr_value,
|
|
"ai": row.ai,
|
|
"ai_model": row.ai_model,
|
|
"genre": row.genre,
|
|
"sample_song": row.sample_song,
|
|
"result_song": row.result_song,
|
|
"created_at": row.created_at.isoformat() if row.created_at else None,
|
|
}
|
|
for row in all_results.fetchall()
|
|
]
|
|
|
|
print(f"전체 {len(results_list)}개의 결과 조회 완료\n")
|
|
|
|
return results_list
|
|
|
|
except HTTPException:
|
|
raise
|
|
except SQLAlchemyError as e:
|
|
print(f"Database Error: {e}")
|
|
import traceback
|
|
|
|
traceback.print_exc()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="데이터베이스 연결에 문제가 발생했습니다.",
|
|
)
|
|
except Exception as e:
|
|
print(f"Unexpected Error: {e}")
|
|
import traceback
|
|
|
|
traceback.print_exc()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="서비스 처리 중 오류가 발생했습니다.",
|
|
)
|
|
|
|
|
|
async def get_song_result(conn: Connection): # 반환 타입 수정
|
|
try:
|
|
select_query = """
|
|
SELECT * FROM song_results_all
|
|
ORDER BY created_at DESC;
|
|
"""
|
|
|
|
all_results = await conn.execute(text(select_query))
|
|
|
|
results_list = [
|
|
{
|
|
"id": row.id,
|
|
"store_info": row.store_info,
|
|
"store_name": row.store_name,
|
|
"store_category": row.store_category,
|
|
"store_address": row.store_address,
|
|
"store_phone_number": row.store_phone_number,
|
|
"description": row.description,
|
|
"prompt": row.prompt,
|
|
"attr_category": row.attr_category,
|
|
"attr_value": row.attr_value,
|
|
"ai": row.ai,
|
|
"ai_model": row.ai_model,
|
|
"season": row.season,
|
|
"num_of_people": row.num_of_people,
|
|
"people_category": row.people_category,
|
|
"genre": row.genre,
|
|
"sample_song": row.sample_song,
|
|
"result_song": row.result_song,
|
|
"created_at": row.created_at.isoformat() if row.created_at else None,
|
|
}
|
|
for row in all_results.fetchall()
|
|
]
|
|
|
|
print(f"전체 {len(results_list)}개의 결과 조회 완료\n")
|
|
|
|
return results_list
|
|
except HTTPException: # HTTPException은 그대로 raise
|
|
raise
|
|
except SQLAlchemyError as e:
|
|
print(f"Database Error: {e}")
|
|
import traceback
|
|
|
|
traceback.print_exc()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="데이터베이스 연결에 문제가 발생했습니다.",
|
|
)
|
|
except Exception as e:
|
|
print(f"Unexpected Error: {e}")
|
|
import traceback
|
|
|
|
traceback.print_exc()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="서비스 처리 중 오류가 발생했습니다.",
|
|
)
|
|
|
|
|
|
async def make_automation(request: Request, conn: Connection):
|
|
try:
|
|
# 1. Form 데이터 파싱
|
|
form_data = await SongFormData.from_form(request)
|
|
|
|
print(f"\n{'=' * 60}")
|
|
print(f"Store ID: {form_data.store_id}")
|
|
print(f"{'=' * 60}\n")
|
|
|
|
# 2. Store 정보 조회
|
|
store_query = """
|
|
SELECT * FROM store_default_info WHERE id=:id;
|
|
"""
|
|
store_result = await conn.execute(text(store_query), {"id": form_data.store_id})
|
|
|
|
all_store_info = [
|
|
StoreData(
|
|
id=row[0],
|
|
store_info=row[1],
|
|
store_name=row[2],
|
|
store_category=row[3],
|
|
store_region=row[4],
|
|
store_address=row[5],
|
|
store_phone_number=row[6],
|
|
created_at=row[7],
|
|
)
|
|
for row in store_result
|
|
]
|
|
|
|
if not all_store_info:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail=f"Store not found: {form_data.store_id}",
|
|
)
|
|
|
|
store_info = all_store_info[0]
|
|
print(f"Store: {store_info.store_name}")
|
|
|
|
# 3. 속성 조회 -- 단계별 선택 프로세서시 구현 필요 없음
|
|
attribute_query = """
|
|
SELECT * FROM attribute;
|
|
"""
|
|
|
|
attribute_results = await conn.execute(text(attribute_query))
|
|
|
|
# 결과 가져오기
|
|
attribute_rows = attribute_results.fetchall()
|
|
|
|
formatted_attributes = ""
|
|
selected_categories = []
|
|
selected_values = []
|
|
|
|
if attribute_rows:
|
|
attribute_list = [
|
|
AttributeData(
|
|
id=row[0],
|
|
attr_category=row[1],
|
|
attr_value=row[2],
|
|
created_at=row[3],
|
|
)
|
|
for row in attribute_rows
|
|
]
|
|
|
|
# ✅ 각 category에서 하나의 value만 랜덤 선택
|
|
formatted_pairs = []
|
|
for attr in attribute_list:
|
|
# 쉼표로 분리 및 공백 제거
|
|
values = [v.strip() for v in attr.attr_value.split(",") if v.strip()]
|
|
|
|
if values:
|
|
# 랜덤하게 하나만 선택
|
|
selected_value = random.choice(values)
|
|
formatted_pairs.append(f"{attr.attr_category} : {selected_value}")
|
|
|
|
# ✅ 선택된 category와 value 저장
|
|
selected_categories.append(attr.attr_category)
|
|
selected_values.append(selected_value)
|
|
|
|
# 최종 문자열 생성
|
|
formatted_attributes = "\n".join(formatted_pairs)
|
|
|
|
print(f"\n[포맷팅된 문자열 속성 정보]\n{formatted_attributes}\n")
|
|
else:
|
|
print("속성 데이터가 없습니다")
|
|
formatted_attributes = ""
|
|
|
|
# 4. 템플릿 가져오기
|
|
print("템플릿 가져오기 (ID=1)")
|
|
|
|
prompts_query = """
|
|
SELECT * FROM prompt_template WHERE id=1;
|
|
"""
|
|
|
|
prompts_result = await conn.execute(text(prompts_query))
|
|
|
|
row = prompts_result.fetchone()
|
|
|
|
if not row:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_404_NOT_FOUND,
|
|
detail="Prompt ID 1 not found",
|
|
)
|
|
|
|
prompt = PromptTemplateData(
|
|
id=row[0],
|
|
description=row[1],
|
|
prompt=row[2],
|
|
)
|
|
|
|
print(f"Prompt Template: {prompt.prompt}")
|
|
|
|
# 5. 템플릿 조합
|
|
|
|
updated_prompt = prompt.prompt.replace("###", formatted_attributes).format(
|
|
name=store_info.store_name or "",
|
|
address=store_info.store_address or "",
|
|
category=store_info.store_category or "",
|
|
description=store_info.store_info or "",
|
|
)
|
|
|
|
print("\n" + "=" * 80)
|
|
print("업데이트된 프롬프트")
|
|
print("=" * 80)
|
|
print(updated_prompt)
|
|
print("=" * 80 + "\n")
|
|
|
|
# 4. Sample Song 조회 및 결합
|
|
combined_sample_song = None
|
|
|
|
if form_data.lyrics_ids:
|
|
print(f"\n[샘플 가사 조회] - {len(form_data.lyrics_ids)}개")
|
|
|
|
lyrics_query = """
|
|
SELECT sample_song FROM song_sample
|
|
WHERE id IN :ids
|
|
ORDER BY created_at;
|
|
"""
|
|
lyrics_result = await conn.execute(
|
|
text(lyrics_query), {"ids": tuple(form_data.lyrics_ids)}
|
|
)
|
|
|
|
sample_songs = [
|
|
row.sample_song for row in lyrics_result.fetchall() if row.sample_song
|
|
]
|
|
|
|
if sample_songs:
|
|
combined_sample_song = "\n\n".join(
|
|
[f"[샘플 {i + 1}]\n{song}" for i, song in enumerate(sample_songs)]
|
|
)
|
|
print(f"{len(sample_songs)}개의 샘플 가사 조회 완료")
|
|
else:
|
|
print("샘플 가사가 비어있습니다")
|
|
else:
|
|
print("선택된 lyrics가 없습니다")
|
|
|
|
# 1. song_sample 테이블의 모든 ID 조회
|
|
print("\n[샘플 가사 랜덤 선택]")
|
|
|
|
all_ids_query = """
|
|
SELECT id FROM song_sample;
|
|
"""
|
|
ids_result = await conn.execute(text(all_ids_query))
|
|
all_ids = [row.id for row in ids_result.fetchall()]
|
|
|
|
print(f"전체 샘플 가사 개수: {len(all_ids)}개")
|
|
|
|
# 2. 랜덤하게 3개 선택 (또는 전체 개수가 3개 미만이면 전체)
|
|
combined_sample_song = None
|
|
|
|
if all_ids:
|
|
# 3개 또는 전체 개수 중 작은 값 선택
|
|
sample_count = min(3, len(all_ids))
|
|
selected_ids = random.sample(all_ids, sample_count)
|
|
|
|
print(f"랜덤 선택된 ID: {selected_ids}")
|
|
|
|
# 3. 선택된 ID로 샘플 가사 조회
|
|
lyrics_query = """
|
|
SELECT sample_song FROM song_sample
|
|
WHERE id IN :ids
|
|
ORDER BY created_at;
|
|
"""
|
|
lyrics_result = await conn.execute(
|
|
text(lyrics_query), {"ids": tuple(selected_ids)}
|
|
)
|
|
|
|
sample_songs = [
|
|
row.sample_song for row in lyrics_result.fetchall() if row.sample_song
|
|
]
|
|
|
|
# 4. combined_sample_song 생성
|
|
if sample_songs:
|
|
combined_sample_song = "\n\n".join(
|
|
[f"[샘플 {i + 1}]\n{song}" for i, song in enumerate(sample_songs)]
|
|
)
|
|
print(f"{len(sample_songs)}개의 샘플 가사 조회 완료")
|
|
else:
|
|
print("샘플 가사가 비어있습니다")
|
|
else:
|
|
print("song_sample 테이블에 데이터가 없습니다")
|
|
|
|
# 5. 프롬프트에 샘플 가사 추가
|
|
if combined_sample_song:
|
|
updated_prompt += f"""
|
|
|
|
다음은 참고해야 하는 샘플 가사 정보입니다.
|
|
|
|
샘플 가사를 참고하여 작곡을 해주세요.
|
|
|
|
{combined_sample_song}
|
|
"""
|
|
print("샘플 가사 정보가 프롬프트에 추가되었습니다")
|
|
else:
|
|
print("샘플 가사가 없어 기본 프롬프트만 사용합니다")
|
|
|
|
print(f"\n[최종 프롬프트 길이: {len(updated_prompt)} 자]\n")
|
|
|
|
# 7. 모델에게 요청
|
|
generated_lyrics = await chatgpt_api.generate_lyrics(prompt=updated_prompt)
|
|
|
|
# 글자 수 계산
|
|
total_chars_with_space = len(generated_lyrics)
|
|
total_chars_without_space = len(
|
|
generated_lyrics.replace(" ", "")
|
|
.replace("\n", "")
|
|
.replace("\r", "")
|
|
.replace("\t", "")
|
|
)
|
|
|
|
# final_lyrics 생성
|
|
final_lyrics = f"""속성 {formatted_attributes}
|
|
전체 글자 수 (공백 포함): {total_chars_with_space}자
|
|
전체 글자 수 (공백 제외): {total_chars_without_space}자\r\n\r\n{generated_lyrics}"""
|
|
|
|
# 8. DB 저장
|
|
insert_query = """
|
|
INSERT INTO song_results_all (
|
|
store_info, store_name, store_category, store_address, store_phone_number,
|
|
description, prompt, attr_category, attr_value,
|
|
ai, ai_model, genre,
|
|
sample_song, result_song, created_at
|
|
) VALUES (
|
|
:store_info, :store_name, :store_category, :store_address, :store_phone_number,
|
|
:description, :prompt, :attr_category, :attr_value,
|
|
:ai, :ai_model, :genre,
|
|
:sample_song, :result_song, NOW()
|
|
);
|
|
"""
|
|
print("\n[insert_params 선택된 속성 확인]")
|
|
print(f"Categories: {selected_categories}")
|
|
print(f"Values: {selected_values}")
|
|
print()
|
|
|
|
# attr_category, attr_value
|
|
insert_params = {
|
|
"store_info": store_info.store_info or "",
|
|
"store_name": store_info.store_name,
|
|
"store_category": store_info.store_category or "",
|
|
"store_address": store_info.store_address or "",
|
|
"store_phone_number": store_info.store_phone_number or "",
|
|
"description": store_info.store_info or "",
|
|
"prompt": prompt.id,
|
|
# 랜덤 선택된 category와 value 사용
|
|
"attr_category": ", ".join(selected_categories)
|
|
if selected_categories
|
|
else "",
|
|
"attr_value": ", ".join(selected_values) if selected_values else "",
|
|
"ai": "ChatGPT",
|
|
"ai_model": "gpt-4o",
|
|
"genre": "후크송",
|
|
"sample_song": combined_sample_song or "없음",
|
|
"result_song": final_lyrics,
|
|
}
|
|
|
|
await conn.execute(text(insert_query), insert_params)
|
|
await conn.commit()
|
|
|
|
print("결과 저장 완료")
|
|
|
|
print("\n전체 결과 조회 중...")
|
|
|
|
# 9. 생성 결과 가져오기 (created_at 역순)
|
|
select_query = """
|
|
SELECT * FROM song_results_all
|
|
ORDER BY created_at DESC;
|
|
"""
|
|
|
|
all_results = await conn.execute(text(select_query))
|
|
|
|
results_list = [
|
|
{
|
|
"id": row.id,
|
|
"store_info": row.store_info,
|
|
"store_name": row.store_name,
|
|
"store_category": row.store_category,
|
|
"store_address": row.store_address,
|
|
"store_phone_number": row.store_phone_number,
|
|
"description": row.description,
|
|
"prompt": row.prompt,
|
|
"attr_category": row.attr_category,
|
|
"attr_value": row.attr_value,
|
|
"ai": row.ai,
|
|
"ai_model": row.ai_model,
|
|
"genre": row.genre,
|
|
"sample_song": row.sample_song,
|
|
"result_song": row.result_song,
|
|
"created_at": row.created_at.isoformat() if row.created_at else None,
|
|
}
|
|
for row in all_results.fetchall()
|
|
]
|
|
|
|
print(f"전체 {len(results_list)}개의 결과 조회 완료\n")
|
|
|
|
return results_list
|
|
|
|
except HTTPException:
|
|
raise
|
|
except SQLAlchemyError as e:
|
|
print(f"Database Error: {e}")
|
|
import traceback
|
|
|
|
traceback.print_exc()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="데이터베이스 연결에 문제가 발생했습니다.",
|
|
)
|
|
except Exception as e:
|
|
print(f"Unexpected Error: {e}")
|
|
import traceback
|
|
|
|
traceback.print_exc()
|
|
raise HTTPException(
|
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
detail="서비스 처리 중 오류가 발생했습니다.",
|
|
)
|