import asyncio import anthropic class AnthropicClient(): def __init__(self, api_key: str): self._client = anthropic.Anthropic(api_key=api_key) @classmethod def new(cls, api_key: str) -> "AnthropicClient": return cls(api_key) def _create_summarise_text_system_prompt( self, complexity_level: str, from_language: str, to_language: str, length_preference="200-400 words", ) -> str: return ( f"You are a language learning content creator.\n" f"You generate original, level-appropriate content from a source.\n" f"The content will be spoken aloud in {to_language}, write it accordingly.\n" f"You will provide content in {to_language} at {complexity_level} proficiency level on the CEFR scale.\n" f"The text you generate will:\n" f"- Contain ONLY the generated summary text in {to_language}.\n" f"- Speak directly to the reader/listener, adopting the tone and style of a semi-formal news reporter or podcaster.\n" f"- Occasionally, where natural, include idiomatic expressions appropriate to {complexity_level} level.\n" f"- Vary tense usage naturally — do not restrict the piece to a single tense.\n" f"- Contain only plain text. The piece should start with a title prefaced like a level-1 markdown title (#), but all other text should be plain. \n" f"- Be around {length_preference} long.\n" f"- Be inspired by the content, but not the tone, of the source material." ) def _create_prompt_summarise_text( self, source_material: str, ) -> str: return ( f"Source material follows: \n\n" f"{source_material}" ) async def generate_summary_text( self, content_to_summarise: str, complexity_level: str, from_language: str, to_language: str, length_preference="200-400 words") -> str: """Generate text using Anthropic.""" def _call() -> str: message = self._client.messages.create( model="claude-sonnet-4-6", max_tokens=1024, system=self._create_summarise_text_system_prompt( complexity_level=complexity_level, from_language=from_language, to_language=to_language, length_preference=length_preference, ), messages=[ { "role": "user", "content": self._create_prompt_summarise_text( content_to_summarise ) } ], ) return message.content[0].text return await asyncio.to_thread(_call)