-
Notifications
You must be signed in to change notification settings - Fork 0
[Feature] Gemini API 대신 Bedrock을 사용하도록 변경 #19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7645030
c2dbe25
5271432
d93a956
c869bb0
0e112fd
93db059
5daec2e
b8bf9b4
8873ce0
adf87f7
3f4c58b
76bddf3
0da4938
d11a59a
2d96096
64b6eee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1 @@ | ||
| google-genai | ||
| boto3 |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,48 +1,71 @@ | ||||||||||
| import enum | ||||||||||
| import json | ||||||||||
| from google import genai | ||||||||||
| from google.genai import types | ||||||||||
| import boto3 | ||||||||||
|
|
||||||||||
| def tos_evaluate(summarized_tos, client): | ||||||||||
| response = client.models.generate_content( | ||||||||||
| model="gemini-2.5-flash-lite", | ||||||||||
| config=types.GenerateContentConfig( | ||||||||||
| system_instruction= | ||||||||||
| """ | ||||||||||
| 당신은 약관 분석 전문가입니다. 주어진 약관 및 각 조항을 평가합니다. | ||||||||||
| 각 약관 조항은 good, neutral, bad 중 하나로 평가합니다. | ||||||||||
| 'good'은 이용자에게 유리한 조항, 'neutral'은 중립적인 조항, 'bad'는 이용자에게 불리한 조항을 의미합니다. | ||||||||||
| A, B, C, D, E 등급 중 하나로 전체 약관을 평가합니다. | ||||||||||
| A는 매우 우수한 약관, E는 매우 불리한 약관을 의미합니다. | ||||||||||
| 한국어로 응답합니다. | ||||||||||
| """, | ||||||||||
| response_mime_type="application/json", | ||||||||||
| response_schema={ | ||||||||||
| "type": "object", | ||||||||||
| "properties": { | ||||||||||
| "overall_evaluation": { | ||||||||||
| "type": "string" | ||||||||||
| }, | ||||||||||
| "evaluation_for_each_clause": { | ||||||||||
| "type": "array", | ||||||||||
| "items": { | ||||||||||
| "type": "object", | ||||||||||
| "properties": { | ||||||||||
| "evaluation": { | ||||||||||
| "type": "string" | ||||||||||
| }, | ||||||||||
| "summarized_clause": { | ||||||||||
| "type": "string" | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
| } | ||||||||||
| ), | ||||||||||
| contents=summarized_tos, | ||||||||||
| def tos_evaluate(summarized_tos): | ||||||||||
| system_instruction=[{"text": """ | ||||||||||
| 당신은 전문적인 약관 분석 AI입니다. 주어진 약관 내용 및 각 조항을 평가합니다. | ||||||||||
| 주어진 약관은 주요 조항을 위주로 요약된 내용입니다. | ||||||||||
| JSON 양식으로, 다음의 key값을 사용합니다. | ||||||||||
| "overall_evaluation": "A|B|C|D|E", | ||||||||||
| "evaluation_for_each_clause": [ | ||||||||||
| "evaluation": "good|neutral|bad", | ||||||||||
| "summarized_clause": "조항 요약 내용" | ||||||||||
| ] | ||||||||||
| "overall_evaluation"은 전체 약관의 등급을 나타냅니다. A는 가장 우수한 약관, E는 가장 불리한 약관입니다. | ||||||||||
| "evaluation_for_each_clause"는 각 조항에 대한 평가를 포함하는 리스트입니다. | ||||||||||
| "evaluation"은 각 조항이 소비자에게 유리한지(good)/중립적인지(neutral)/불리한지(bad)를 나타냅니다. | ||||||||||
| "summarized_clause"는 각 조항의 요약된 내용을 포함합니다. | ||||||||||
| JSON 형식 이외에 서론이나 결론, 코드 블럭 따위는 절대로 포함하지 마십시오. | ||||||||||
| 응답은 곧바로 json.loads()를 통해 파싱되기 때문에 반드시 여는 중괄호(`{`})로 시작하고 닫는 중괄호(`}`)로 끝나야 합니다. | ||||||||||
| 예시 응답: | ||||||||||
| { | ||||||||||
| "overall_evaluation": "D", | ||||||||||
| "evaluation_for_each_clause": [ | ||||||||||
| { | ||||||||||
| "evaluation": "neutral", | ||||||||||
| "summarized_clause": "AWS 사이트 콘텐츠의 저작권은 AWS 또는 제공자에게 있으며, 관련 법률에 의해 보호됨을 명시합니다." | ||||||||||
| }, | ||||||||||
| { | ||||||||||
| "evaluation": "neutral", | ||||||||||
| "summarized_clause": "AWS 상표 및 트레이드 드레스는 허가 없이 사용할 수 없으며, 타사 상표는 해당 소유자에게 있음을 명시합니다." | ||||||||||
| }, | ||||||||||
| { | ||||||||||
| "evaluation": "bad", | ||||||||||
| "summarized_clause": "개인적인 사이트 이용 목적 외 상업적 재판매, 복제, 변경 등은 사전 서면 동의 없이는 금지됨을 명시하며, 이는 일반적인 내용이나 명확한 제한을 둠." | ||||||||||
| }, | ||||||||||
| { | ||||||||||
| "evaluation": "bad", | ||||||||||
| "summarized_clause": "이용자의 계정 및 비밀번호 관리 책임을 명시하고, 계정 활동에 대한 책임을 이용자에게 부과합니다. 또한 AWS는 일방적으로 서비스 거절 및 계정 해지 권한을 가집니다." | ||||||||||
| } | ||||||||||
| ] | ||||||||||
| } | ||||||||||
| """}] | ||||||||||
| client = boto3.client( | ||||||||||
| service_name="bedrock-runtime", | ||||||||||
| region_name="us-west-2" | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| model_id = "us.anthropic.claude-sonnet-4-5-20250929-v1:0" | ||||||||||
|
||||||||||
| messages = [{ | ||||||||||
| "role": "user", | ||||||||||
| "content": [ | ||||||||||
| {"text": summarized_tos} | ||||||||||
| ] | ||||||||||
| }] | ||||||||||
|
|
||||||||||
| response = client.converse( | ||||||||||
| modelId=model_id, | ||||||||||
| system=system_instruction, | ||||||||||
| messages=messages, | ||||||||||
| ) | ||||||||||
|
Comment on lines
+56
to
60
|
||||||||||
|
|
||||||||||
| # response에서 JSON 파싱 후 반환 | ||||||||||
| print("TOS Evaluation Response:") | ||||||||||
| print(response) | ||||||||||
|
Comment on lines
+62
to
+63
|
||||||||||
|
|
||||||||||
| return json.loads(response.text) | ||||||||||
| text = response['output']['message']['content'][0]['text'] | ||||||||||
| start = text.find('{') | ||||||||||
| end = text.rfind('}') + 1 | ||||||||||
|
||||||||||
| end = text.rfind('}') + 1 | |
| end = text.rfind('}') + 1 | |
| if start == -1 or end == 0 or end <= start: | |
| raise ValueError("No valid JSON object found in the response text.") |
Copilot
AI
Nov 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The json.loads() call can raise json.JSONDecodeError if the extracted text is not valid JSON. This exception is not handled and will cause the Lambda function to fail. Wrap this in a try-except block to catch and handle JSON parsing errors gracefully.
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,18 +1,32 @@ | ||||||||||||
| import json | ||||||||||||
| from google import genai | ||||||||||||
| from google.genai import types | ||||||||||||
| import boto3 | ||||||||||||
|
|
||||||||||||
| def tos_summarize(text_html, client): | ||||||||||||
| response = client.models.generate_content( | ||||||||||||
| model="gemini-2.5-flash-lite", | ||||||||||||
| config=types.GenerateContentConfig( | ||||||||||||
| system_instruction=""" | ||||||||||||
| 당신은 약관 분석 전문가입니다. | ||||||||||||
| 주어진 html 페이지에서 주요 약관 내용을 요약합니다. | ||||||||||||
| 한국어로 응답합니다. | ||||||||||||
| """, | ||||||||||||
| ), | ||||||||||||
| contents=text_html, | ||||||||||||
| def tos_summarize(text_html): | ||||||||||||
| system_instruction=[{"text": """ | ||||||||||||
| 당신은 약관 분석 전문가입니다. | ||||||||||||
| 주어진 html 페이지에서 주요 약관 내용을 요약합니다. | ||||||||||||
| 한국어로 응답합니다. | ||||||||||||
| """}] | ||||||||||||
|
|
||||||||||||
| client = boto3.client( | ||||||||||||
| service_name="bedrock-runtime", | ||||||||||||
| region_name="us-west-2" | ||||||||||||
| ) | ||||||||||||
|
Comment on lines
+10
to
13
|
||||||||||||
|
|
||||||||||||
| return response.text | ||||||||||||
| model_id = "us.anthropic.claude-sonnet-4-5-20250929-v1:0" | ||||||||||||
| messages = [{ | ||||||||||||
| "role": "user", | ||||||||||||
| "content": [ | ||||||||||||
| {"text": text_html} | ||||||||||||
| ] | ||||||||||||
| }] | ||||||||||||
|
|
||||||||||||
| response = client.converse( | ||||||||||||
| modelId=model_id, | ||||||||||||
| system=system_instruction, | ||||||||||||
| messages=messages, | ||||||||||||
| ) | ||||||||||||
|
Comment on lines
+23
to
+27
|
||||||||||||
|
|
||||||||||||
| print("TOS Summarization Response:") | ||||||||||||
| print(response) | ||||||||||||
|
Comment on lines
+29
to
+30
|
||||||||||||
| print("TOS Summarization Response:") | |
| print(response) | |
| # If needed, use logging for debug information: | |
| # import logging | |
| # logging.debug("TOS Summarization Response: %s", response) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The boto3 client is created on every function invocation. In AWS Lambda, clients should be initialized outside the handler function to leverage connection pooling and reduce cold start overhead. Consider moving the client creation outside the
tos_evaluatefunction or making it a module-level singleton.