Corin1998 commited on
Commit
3cdcdbe
·
verified ·
1 Parent(s): fe7a9c2

Create main.py

Browse files
Files changed (1) hide show
  1. backend/app/main.py +63 -0
backend/app/main.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from .schemas import GenerateRequest, EmailResponse, ProposalResponse, LintRequest, LintResponse
4
+ from .prompt_templates import EMAIL_SYSTEM, EMAIL_USER, PROPOSAL_SYSTEM, PROPOSAL_USER
5
+ from .openai_utils import chat_complete, split_subject_body
6
+ from .hf_utils import toxicity_score, sentiment_polarity
7
+
8
+ app = FastAPI(title="Sales Writer API", version="0.1.0")
9
+
10
+ # 必要に応じてオリジン制限
11
+ app.add_middleware(
12
+ CORSMiddleware,
13
+ allow_origins=["http://localhost:5173"],
14
+ allow_credentials=True,
15
+ allow_methods=["*"],
16
+ allow_headers=["*"],
17
+ )
18
+
19
+ @app.get("/health")
20
+ def health():
21
+ return {"status": "ok"}
22
+
23
+ @app.post("/generate/email", response_model=EmailResponse)
24
+ async def generate_email(req: GenerateRequest):
25
+ user_prompt = EMAIL_USER.format(**req.model_dump())
26
+ raw = chat_complete(EMAIL_SYSTEM, user_prompt)
27
+ subject, body = split_subject_body(raw)
28
+
29
+ tox = await toxicity_score(body)
30
+ sent = await sentiment_polarity(body)
31
+ warnings = []
32
+ if tox > 0.2:
33
+ warnings.append("トーンが攻撃的/不適切の可能性があります。表現を柔らかくしてください。")
34
+
35
+ quality = {"toxicity": tox, "sentiment": sent}
36
+ return EmailResponse(subject=subject, body=body, quality=quality, warnings=warnings)
37
+
38
+ @app.post("/generate/proposal", response_model=ProposalResponse)
39
+ async def generate_proposal(req: GenerateRequest):
40
+ user_prompt = PROPOSAL_USER.format(**req.model_dump())
41
+ text = chat_complete(PROPOSAL_SYSTEM, user_prompt)
42
+ # 簡易パース:先頭の箇条書きを章立て、最後の段落をサマリーと仮定
43
+ lines = [ln.strip("-• ").strip() for ln in text.splitlines() if ln.strip()]
44
+ outline = [ln for ln in lines if not ln.startswith("エグゼクティブサマリー")]
45
+ # サマリー抽出(雑だがMVP)
46
+ summary = ""
47
+ for i, ln in enumerate(lines):
48
+ if "エグゼクティブサマリー" in ln:
49
+ summary = "\n".join(lines[i+1:])
50
+ break
51
+ return ProposalResponse(outline=outline[:8], executive_summary=summary or "(サマリー抽出に失敗しました)")
52
+
53
+ @app.post("/lint", response_model=LintResponse)
54
+ async def lint_text(req: LintRequest):
55
+ tox = await toxicity_score(req.text)
56
+ issues = []
57
+ if tox > 0.2:
58
+ issues.append("不適切・攻撃的な表現を含む可能性")
59
+ # 営業で避けたいフレーズ例(簡易ルール)
60
+ bad_patterns = ["絶対に", "必ず儲かる", "今だけ", "無料で全部"]
61
+ if any(p in req.text for p in bad_patterns):
62
+ issues.append("誇大広告と見なされる恐れのある表現")
63
+ return LintResponse(issues=issues, toxicity=tox)