flashcards / flashcard.py
AdamyaG's picture
Upload 6 files
d291776 verified
""" File that contains flashcards' backend """
import json
import os
from dataclasses import asdict, dataclass
# from dotenv import find_dotenv, load_dotenv
from langchain.chat_models import ChatOpenAI
from langchain.output_parsers import ResponseSchema, StructuredOutputParser
from langchain.prompts import ChatPromptTemplate
@dataclass
class Flashcard:
"""
Represents a flashcard containing language translation information.
Attributes:
input_expression (str): The expression in the input language.
input_language (str): The language of the input expression.
output_expression (str): The translated expression in the output language.
output_language (str): The language of the output expression.
example_usage (str): An example usage of the input expression in a sentence.
"""
input_expression: str
input_language: str
output_expression: str
output_language: str
example_usage: str
@classmethod
def from_dict(cls, data: dict) -> "Flashcard":
"""
Creates a Flashcard instance from a dictionary of attributes.
Args:
data (dict): A dictionary containing flashcard attributes.
Returns:
Flashcard: An instance of Flashcard.
"""
return cls(
input_expression=data.get("input_expression", None),
input_language=data.get("input_language", None),
output_expression=data.get("output_expression", None),
output_language=data.get("output_language", None),
example_usage=data.get("example_usage", None),
)
@dataclass
class Flashcards:
"""
Represents a collection of Flashcard instances.
Attributes:
data (list[Flashcard]): A list of Flashcard instances.
"""
data: list[Flashcard]
def as_json(self) -> dict:
"""
Converts the collection of Flashcard instances to a JSON format.
Returns:
dict: A dictionary representing the flashcards in JSON format.
"""
return {"flashcards": [asdict(card) for card in self.data]}
@classmethod
def import_from_json(cls, data: dict) -> "Flashcards":
"""
Creates a Flashcards instance from a JSON file.
Args:
data (file): A JSON file containing flashcard data.
Returns:
Flashcards: An instance of Flashcards containing the imported data.
"""
data = json.load(data)
flashcard_objects = [Flashcard(**card) for card in data["flashcards"]]
return cls(data=flashcard_objects)
def __len__(self) -> int:
"""
Returns the number of Flashcard instances in the collection.
Returns:
int: The number of Flashcard instances.
"""
return len(self.data)
class FlashcardGeneratorOpenAI: # pylint: disable=R0903
"""
A class to generate language learning flashcards using OpenAI's language model.
Attributes:
chat (ChatOpenAI): An instance of ChatOpenAI for generating flashcards.
response_schemas (list): A list of ResponseSchema objects for structuring the response.
output_parser (StructuredOutputParser): Parser to structure the output
from the language model.
flashcard_generator_template (str): A template for generating flashcard data.
prompt (ChatPromptTemplate): A prompt template for the language model.
"""
def __init__(self, api_key: str, llm_model: str = "gpt-3.5-turbo") -> None:
"""
Initializes the FlashcardGeneratorOpenAI class with
the specified API key and language model.
Args:
api_key (str): The API key for OpenAI.
llm_model (str): The name of the language model to use.
"""
self.chat = ChatOpenAI(temperature=0.0, model=llm_model, api_key=api_key)
input_expression_schema = ResponseSchema(
name="input_expression",
type="str",
description="Original expression entered by the user, refined"
" to create translated_expression.",
)
input_language_schema = ResponseSchema(
name="input_language",
type="str",
description="Language of the input expression.",
)
output_expression_schema = ResponseSchema(
name="output_expression",
type="str",
description="Translation of refined expression entered by the user.",
)
output_language_schema = ResponseSchema(
name="output_language",
type="str",
description="Language of the output expression.",
)
example_usage_schema = ResponseSchema(
name="example_usage",
type="str",
description="Example usage of input expression, used to give the user some "
"example context where it could be used. Limited to one sentence.",
)
response_schemas = [
input_expression_schema,
input_language_schema,
output_expression_schema,
output_language_schema,
example_usage_schema,
]
self.output_parser = StructuredOutputParser.from_response_schemas(
response_schemas
)
self.format_instructions = self.output_parser.get_format_instructions()
self.flashcard_generator_template = """\
For the following expression, extract the following information:
input_expression: Original expression entered by the user, but refined to create translated_expression (for flashcard for language learning). If the expression is too long (more than 10 words), it should be shortened while keeping the sense.
input_language: Language of the input expression
output_expression: Refined input expression translated to {output_language} language. Provide 2 alternatives, separated with 'slash' sign (and space before & after the sign).
example_usage: Example usage of input expression, used to give the user some example context where it could be used. Limited to one sentence.
input_expression: {input_expression}
input_language: {input_language}
{format_instructions}
"""
self.prompt = ChatPromptTemplate.from_template(
template=self.flashcard_generator_template
)
def generate_flashcard(
self, input_exp: str, input_lang: str, output_lang: str
) -> Flashcard:
"""
Generates a flashcard by translating an input expression from one language to another.
This method takes an expression in a specified input language, translates it into
a specified output language, and then creates a flashcard containing both the original
and translated expressions. It uses the ChatOpenAI model to generate the translation
and example usage.
Args:
input_expression (str): The expression to be translated.
input_language (str): The language of the input expression.
output_language (str): The language into which the input expression is to be translated.
Returns:
Flashcard: An instance of the Flashcard class containing the original expression,
its translation, and an example usage in the output language.
"""
messages = self.prompt.format_messages(
input_expression=input_exp,
input_language=input_lang,
output_language=output_lang,
format_instructions=self.format_instructions,
)
response = self.chat(messages)
flashcard_dict = self.output_parser.parse(response.content)
return Flashcard.from_dict(flashcard_dict)
def main():
"""
For debugging purposes only
"""
# _ = load_dotenv(find_dotenv()) # Read local .env file
generator = FlashcardGeneratorOpenAI(api_key=os.environ["OPENAI_API_KEY"])
input_expressions = [
"cruel",
"let someone off the hook",
"it absorbed me",
"get my thoughts in order",
"crude",
"pore over",
]
input_language = "English"
output_language = "Polish"
flashcards = Flashcards([])
for input_expression in input_expressions:
flashcard = generator.generate_flashcard(
input_expression, input_language, output_language
)
print(flashcard)
flashcards.data.append(flashcard)
if __name__ == "__main__":
main()