Spaces:
Running
Running
import json | |
from typing import Literal | |
from pydantic import BaseModel | |
import litellm | |
from litellm.types.utils import ModelResponse | |
SAFETY_SETTINGS = [ | |
{ | |
"category": "HARM_CATEGORY_HARASSMENT", | |
"threshold": "BLOCK_NONE", | |
}, | |
{ | |
"category": "HARM_CATEGORY_HATE_SPEECH", | |
"threshold": "BLOCK_NONE", | |
}, | |
{ | |
"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", | |
"threshold": "BLOCK_NONE", | |
}, | |
{ | |
"category": "HARM_CATEGORY_DANGEROUS_CONTENT", | |
"threshold": "BLOCK_NONE", | |
}, | |
] | |
class BloggerAgent: | |
instructions = [ | |
{ | |
"role": "user", | |
"content": "与えられる情報について、重要なポイントを踏まえて平易な言葉で解説・紹介する記事を書いてください", | |
}, | |
] | |
model: str = "gemini/gemini-2.5-flash-preview-05-20" | |
temperature: float = 1.0 | |
max_tokens: int = 4096 | |
thinking_budget: int = 1024 | |
api_key: str | |
def __init__(self, api_key: str): | |
self.api_key = api_key | |
async def task(self, information: str) -> str: | |
messages = self.instructions.copy() | |
messages.append({"role": "user", "content": information}) | |
res = await litellm.acompletion( | |
api_key=self.api_key, | |
model=self.model, | |
messages=messages, | |
temperature=self.temperature, | |
max_completion_tokens=self.max_tokens, | |
thinking={"type": "enabled", "budget_tokens": self.thinking_budget}, | |
safety_settings=SAFETY_SETTINGS, | |
) | |
assert isinstance(res, ModelResponse) | |
blog = res.choices[0].message.content | |
assert isinstance(blog, str) | |
return blog | |
class WriterAgent: | |
instructions = [ | |
{ | |
"role": "user", | |
"content": """与えられる情報ソースとその解説記事をもとに、コンテンツを紹介する Podcast の会話を作成してください。 | |
Podcast では、二人の人物が交互に会話をします。 | |
# 登場人物 | |
- スピーカー: コンテンツ紹介をリードする人で、主にこの人物が解説を行う | |
- サポーター: スピーカーの説明を聞き、うなづいたり、さらに質問を投げかけることで、理解を助ける。 | |
# 構成 | |
1. イントロ: まず、スピーカーとサポーターが何について話すのか、挨拶を交えながら会話します。自己紹介は省略する。 | |
2. 解説: 前提知識の確認をしながら、内容を解説していきます | |
3. アウトロ: 今後の展望を交えながら締めくくります | |
--- | |
このような内容になるような Podcast の脚本を作成してください。 | |
""".strip(), | |
}, | |
] | |
model: str = "gemini/gemini-2.5-flash-preview-05-20" | |
temperature: float = 1.0 | |
max_tokens: int = 4096 | |
thinking_budget: int = 1024 | |
api_key: str | |
def __init__(self, api_key: str): | |
self.api_key = api_key | |
async def task(self, information: str, blog: str) -> str: | |
messages = self.instructions.copy() | |
messages.append( | |
{"role": "user", "content": f"# 情報\n{information}\n\n# 解説\n{blog}"} | |
) | |
res = await litellm.acompletion( | |
api_key=self.api_key, | |
model=self.model, | |
messages=messages, | |
temperature=self.temperature, | |
max_completion_tokens=self.max_tokens, | |
thinking={"type": "enabled", "budget_tokens": self.thinking_budget}, | |
safety_settings=SAFETY_SETTINGS, | |
) | |
assert isinstance(res, ModelResponse) | |
dialogue = res.choices[0].message.content | |
assert isinstance(dialogue, str) | |
return dialogue | |
class Dialogue(BaseModel): | |
role: Literal["speaker", "supporter"] | |
content: str | |
class Conversation(BaseModel): | |
conversation: list[Dialogue] | |
class StructureAgent: | |
instructions = [ | |
{ | |
"role": "user", | |
"content": """この会話を指定されたスキーマに従った形に変換してください。スピーカーの role は `speaker`、サポーターは `supporter` です。""".strip(), | |
}, | |
] | |
model: str = "gemini/gemini-2.5-flash-preview-05-20" | |
temperature: float = 0.1 | |
max_tokens: int = 12_288 | |
thinking_budget: int = 0 | |
api_key: str | |
def __init__(self, api_key: str): | |
self.api_key = api_key | |
async def task(self, dialogue: str) -> Conversation: | |
messages = self.instructions.copy() | |
messages.append({"role": "user", "content": dialogue}) | |
res = await litellm.acompletion( | |
api_key=self.api_key, | |
model=self.model, | |
messages=messages, | |
temperature=self.temperature, | |
max_completion_tokens=self.max_tokens, | |
thinking={"type": "disabled"}, | |
response_format=Conversation, | |
safety_settings=SAFETY_SETTINGS, | |
) | |
conversation = Conversation.model_validate( | |
json.loads(res.choices[0].message.content) | |
) | |
return conversation | |