-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathapp.py
More file actions
97 lines (76 loc) · 3.69 KB
/
app.py
File metadata and controls
97 lines (76 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
from langchain import LLMChain, PromptTemplate
from config import llm
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
from typing import List, Optional
from fastapi.middleware.cors import CORSMiddleware
# --------- judge.py ---------
judge_template = PromptTemplate(
input_variables=["personas", "criteria"],
template="""
System:
너는 텍스트 기반 카드 배틀의 심판이다.
주어진 판정 기준에 따라 두 캐릭터 중 더 우수한 캐릭터를 판정하라.
판정 기준: {criteria}
캐릭터 설명: {personas}
AI:
위의 판정 기준(criteria)와 캐릭터 설명(personas)을 반드시 참고하여 두 캐릭터 중 승자를 결정하라.
사용자가 제시한 판정 기준과 캐릭터 설명에 등장하는 모든 특징들을 반드시 연결하여 판단하라.
판정 기준이 애매하거나 캐릭터 설명과 직접 연결되지 않을 경우, AI가 언어적 암시를 활용해 적절히 해석하고 그 결과를 이유 문장에 자연스럽게 녹여내야 한다.
단, 성별과 나이는 판단에 반영하지 말고, 그 외 특징들을 중심으로 평가하라.
승자는 이름만 제시하고,
이유는 RPG 전투 묘사 스타일로 자세하고 생생하게 정확히 두 개의 완전한 문장으로 작성하라.
첫 문장은 전투현장을 설명하고 다음 문장은 판정기준에 따라서 승패 이유를 명확하게 설명하라.
각 문장은 마침표(.)로 끝나야 하며, 중간에 끊기지 않도록 연결하라.
[출력 형식]
승자: [캐릭터 이름]
이유: [전투 상황을 묘사한 문장]. [판정 기준에 따른 승리 이유를 설명하는 문장].
[예시 출력]
승자: 토토로
이유: 토토로는 거대한 몸집을 내세워 땅을 쿵쿵 울리며 상대의 균형을 무너뜨리고, 회오리치는 바람을 일으켜 전장을 휘감았다. 자연과 하나 된 그의 압도적인 위압감은 상대의 움직임을 봉쇄하며, 판정 기준인 자연 친화력과 위압감에서 압도적인 우위를 점했다.
"""
)
judge_chain = LLMChain(llm=llm, prompt=judge_template)
def decide_winner(characters: list, judge_criteria: str = "공정하고 객관적인 기준") -> str:
personas_str = "\n".join([f"{c['name']}: {c['desc']}" for c in characters])
return judge_chain.run({
"personas": personas_str,
"criteria": judge_criteria
})
# --------- FastAPI 설정 ---------
app = FastAPI(title="Multi-Persona Battle API")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
class CharacterInfo(BaseModel):
name: str
persona_main: str
persona_detail: str
gender: str
age: int
weakness: str
attack_power: int = Field(..., alias="attack_power")
class BattleRequest(BaseModel):
characters: List[CharacterInfo]
criteria: Optional[str] = "공정하고 객관적인 기준"
class BattleResponse(BaseModel):
result: str
@app.post("/api/battle", response_model=BattleResponse)
async def battle(req: BattleRequest):
try:
characters = req.characters
personas = [
{"name": character.name, "desc": f"{character.persona_main}, {character.persona_detail}, 나이: {character.age}, 성별: {character.gender}, 공격력: {character.attack_power}, 약점: {character.weakness}"}
for character in characters
]
verdict = decide_winner(
characters=personas,
judge_criteria=req.criteria
)
return BattleResponse(result=verdict)
except Exception as e:
raise HTTPException(status_code=500, detail=f"전투 처리 중 오류: {e}")