53 lines
2.4 KiB
Python
53 lines
2.4 KiB
Python
"""ScriptModifier — LLM 으로 협상 스크립트 어조/내용을 다듬되 구조·치환자·스타일 보존.
|
|
|
|
openai SDK 직접 호출(langchain 미사용). 프롬프트 문구는 우리 자체 작성(CLEANROOM.md).
|
|
LLM 미설정/실패 시 원본을 그대로 반환(안전 폴백).
|
|
"""
|
|
|
|
import json
|
|
import logging
|
|
from typing import Optional
|
|
|
|
from negotiation.profiling.config import LlmCredentials
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
_SYSTEM = """역할: 협상 스크립트 문장 다듬기 도우미.
|
|
입력은 JSON 블록 리스트다. 각 블록의 text 만 다듬고 그 외 모든 것은 그대로 둔다.
|
|
규칙:
|
|
- 출력은 입력과 동일 구조의 유효한 JSON 이어야 한다. {"script": [...]} 형태로 반환한다.
|
|
- {price} 같은 치환자는 추가/삭제/변경하지 않는다. 입력에 있던 것만 유지한다.
|
|
- color/bold 등 스타일 키와 children 배열 구조는 변경하지 않는다.
|
|
- text 값만 요청된 어조/맥락에 맞게 자연스럽게 다시 쓴다(한국어).
|
|
- 새로운 키를 추가하지 않는다."""
|
|
|
|
|
|
class ScriptModifier:
|
|
def __init__(self, creds: Optional[LlmCredentials] = None):
|
|
self._creds = creds
|
|
|
|
def is_available(self) -> bool:
|
|
creds = self._creds or LlmCredentials.from_config()
|
|
return creds.is_configured()
|
|
|
|
def modify_script(self, original_script: list, context: dict = None) -> list:
|
|
"""context(예: {'tone': 'polite'})에 맞춰 스크립트 텍스트 수정. 실패 시 원본 반환."""
|
|
if not original_script or not isinstance(original_script, list):
|
|
return original_script
|
|
try:
|
|
from negotiation.profiling.infra.llm_adapter import chat_json
|
|
|
|
messages = [
|
|
{"role": "system", "content": _SYSTEM},
|
|
{"role": "user", "content":
|
|
"원본 스크립트:\n" + json.dumps(original_script, ensure_ascii=False) +
|
|
"\n\n맥락/지시:\n" + json.dumps(context or {}, ensure_ascii=False) +
|
|
"\n\n위 규칙대로 다듬어 {\"script\": [...]} 로 출력."},
|
|
]
|
|
result = chat_json(messages, creds=self._creds)
|
|
modified = result.get("script", result) if isinstance(result, dict) else result
|
|
return modified if isinstance(modified, list) else original_script
|
|
except Exception as e:
|
|
logger.error(f"Failed to modify script via LLM: {e}")
|
|
return original_script
|