diff --git a/README.md b/README.md
index 211f848..cf781bc 100644
--- a/README.md
+++ b/README.md
@@ -266,6 +266,37 @@ print(result.response)
+
+
+ Use LeMUR to with Input Text
+
+```python
+import assemblyai as aai
+
+transcriber = aai.Transcriber()
+config = aai.TranscriptionConfig(
+ speaker_labels=True,
+)
+transcript = transcriber.transcribe("https://example.org/customer.mp3", config=config)
+
+# Example converting speaker label utterances into LeMUR input text
+text = ""
+
+for utt in transcript.utterances:
+ text += f"Speaker {utt.speaker}:\n{utt.text}\n"
+
+result = aai.Lemur().task(
+ "You are a helpful coach. Provide an analysis of the transcript "
+ "and offer areas to improve with exact quotes. Include no preamble. "
+ "Start with an overall summary then get into the examples with feedback.",
+ input_text=text
+)
+
+print(result.response)
+```
+
+
+
Delete data previously sent to LeMUR
diff --git a/assemblyai/lemur.py b/assemblyai/lemur.py
index 5debd48..c81ab34 100644
--- a/assemblyai/lemur.py
+++ b/assemblyai/lemur.py
@@ -14,7 +14,11 @@ def __init__(
) -> None:
self._client = client
- self._sources = [types.LemurSourceRequest.from_lemur_source(s) for s in sources]
+ self._sources = (
+ [types.LemurSourceRequest.from_lemur_source(s) for s in sources]
+ if sources is not None
+ else []
+ )
def question(
self,
@@ -24,6 +28,7 @@ def question(
final_model: Optional[types.LemurModel],
max_output_size: Optional[int],
temperature: Optional[float],
+ input_text: Optional[str],
) -> types.LemurQuestionResponse:
response = api.lemur_question(
client=self._client.http_client,
@@ -34,6 +39,7 @@ def question(
final_model=final_model,
max_output_size=max_output_size,
temperature=temperature,
+ input_text=input_text,
),
http_timeout=timeout,
)
@@ -48,6 +54,7 @@ def summarize(
max_output_size: Optional[int],
timeout: Optional[float],
temperature: Optional[float],
+ input_text: Optional[str],
) -> types.LemurSummaryResponse:
response = api.lemur_summarize(
client=self._client.http_client,
@@ -58,6 +65,7 @@ def summarize(
final_model=final_model,
max_output_size=max_output_size,
temperature=temperature,
+ input_text=input_text,
),
http_timeout=timeout,
)
@@ -72,6 +80,7 @@ def action_items(
max_output_size: Optional[int],
timeout: Optional[float],
temperature: Optional[float],
+ input_text: Optional[str],
) -> types.LemurActionItemsResponse:
response = api.lemur_action_items(
client=self._client.http_client,
@@ -82,6 +91,7 @@ def action_items(
final_model=final_model,
max_output_size=max_output_size,
temperature=temperature,
+ input_text=input_text,
),
http_timeout=timeout,
)
@@ -95,6 +105,7 @@ def task(
max_output_size: Optional[int],
timeout: Optional[float],
temperature: Optional[float],
+ input_text: Optional[str],
):
response = api.lemur_task(
client=self._client.http_client,
@@ -104,6 +115,7 @@ def task(
final_model=final_model,
max_output_size=max_output_size,
temperature=temperature,
+ input_text=input_text,
),
http_timeout=timeout,
)
@@ -121,7 +133,7 @@ class Lemur:
def __init__(
self,
- sources: List[types.LemurSource],
+ sources: Optional[List[types.LemurSource]] = None,
client: Optional[_client.Client] = None,
) -> None:
"""
@@ -147,6 +159,7 @@ def question(
max_output_size: Optional[int] = None,
timeout: Optional[float] = None,
temperature: Optional[float] = None,
+ input_text: Optional[str] = None,
) -> types.LemurQuestionResponse:
"""
Question & Answer allows you to ask free form questions about one or many transcripts.
@@ -178,6 +191,7 @@ def question(
max_output_size=max_output_size,
timeout=timeout,
temperature=temperature,
+ input_text=input_text,
)
def summarize(
@@ -188,6 +202,7 @@ def summarize(
max_output_size: Optional[int] = None,
timeout: Optional[float] = None,
temperature: Optional[float] = None,
+ input_text: Optional[str] = None,
) -> types.LemurSummaryResponse:
"""
Summary allows you to distill a piece of audio into a few impactful sentences.
@@ -214,6 +229,7 @@ def summarize(
max_output_size=max_output_size,
timeout=timeout,
temperature=temperature,
+ input_text=input_text,
)
def action_items(
@@ -224,6 +240,7 @@ def action_items(
max_output_size: Optional[int] = None,
timeout: Optional[float] = None,
temperature: Optional[float] = None,
+ input_text: Optional[str] = None,
) -> types.LemurActionItemsResponse:
"""
Action Items allows you to generate action items from one or many transcripts.
@@ -251,6 +268,7 @@ def action_items(
max_output_size=max_output_size,
timeout=timeout,
temperature=temperature,
+ input_text=input_text,
)
def task(
@@ -260,6 +278,7 @@ def task(
max_output_size: Optional[int] = None,
timeout: Optional[float] = None,
temperature: Optional[float] = None,
+ input_text: Optional[str] = None,
) -> types.LemurTaskResponse:
"""
Task feature allows you to submit a custom prompt to the model.
@@ -282,6 +301,7 @@ def task(
max_output_size=max_output_size,
timeout=timeout,
temperature=temperature,
+ input_text=input_text,
)
@classmethod
diff --git a/assemblyai/types.py b/assemblyai/types.py
index d913a11..f34243c 100644
--- a/assemblyai/types.py
+++ b/assemblyai/types.py
@@ -1773,6 +1773,7 @@ class BaseLemurRequest(BaseModel):
final_model: Optional[LemurModel]
max_output_size: Optional[int]
temperature: Optional[float]
+ input_text: Optional[str]
class LemurTaskRequest(BaseLemurRequest):
diff --git a/tests/unit/test_lemur.py b/tests/unit/test_lemur.py
index 0d753a6..d273112 100644
--- a/tests/unit/test_lemur.py
+++ b/tests/unit/test_lemur.py
@@ -14,7 +14,7 @@
aai.settings.api_key = "test"
-def test_lemur_single_question_succeeds(httpx_mock: HTTPXMock):
+def test_lemur_single_question_succeeds_transcript(httpx_mock: HTTPXMock):
"""
Tests whether asking a single question succeeds.
"""
@@ -64,7 +64,54 @@ def test_lemur_single_question_succeeds(httpx_mock: HTTPXMock):
assert len(httpx_mock.get_requests()) == 1
-def test_lemur_multiple_question_succeeds(httpx_mock: HTTPXMock):
+def test_lemur_single_question_succeeds_input_text(httpx_mock: HTTPXMock):
+ """
+ Tests whether asking a single question succeeds with input text.
+ """
+
+ # create a mock response of a LemurQuestionResponse
+ mock_lemur_answer = factories.generate_dict_factory(
+ factories.LemurQuestionResponse
+ )()
+
+ # we only want to mock one answer
+ mock_lemur_answer["response"] = [mock_lemur_answer["response"][0]]
+
+ # mock the specific endpoints
+ httpx_mock.add_response(
+ url=f"{aai.settings.base_url}{ENDPOINT_LEMUR}/question-answer",
+ status_code=httpx.codes.OK,
+ method="POST",
+ json=mock_lemur_answer,
+ )
+
+ # prepare the question to be asked
+ question = aai.LemurQuestion(
+ question="Which cars do the callers want to buy?",
+ context="Callers are interested in buying cars",
+ answer_options=["Toyota", "Honda", "Ford", "Chevrolet"],
+ )
+ # test input_text input
+ # mimic the usage of the SDK
+ lemur = aai.Lemur()
+ result = lemur.question(
+ question, input_text="This transcript is a test transcript."
+ )
+
+ # check whether answer is not a list
+ assert isinstance(result, aai.LemurQuestionResponse)
+
+ answers = result.response
+
+ # check the response
+ assert answers[0].question == mock_lemur_answer["response"][0]["question"]
+ assert answers[0].answer == mock_lemur_answer["response"][0]["answer"]
+
+ # check whether we mocked everything
+ assert len(httpx_mock.get_requests()) == 1
+
+
+def test_lemur_multiple_question_succeeds_transcript(httpx_mock: HTTPXMock):
"""
Tests whether asking multiple questions succeeds.
"""
@@ -117,6 +164,59 @@ def test_lemur_multiple_question_succeeds(httpx_mock: HTTPXMock):
assert len(httpx_mock.get_requests()) == 1
+def test_lemur_multiple_question_succeeds_input_text(httpx_mock: HTTPXMock):
+ """
+ Tests whether asking multiple questions succeeds.
+ """
+
+ # create a mock response of a LemurQuestionResponse
+ mock_lemur_answer = factories.generate_dict_factory(
+ factories.LemurQuestionResponse
+ )()
+
+ # prepare the questions to be asked
+ questions = [
+ aai.LemurQuestion(
+ question="Which cars do the callers want to buy?",
+ ),
+ aai.LemurQuestion(
+ question="What price range are the callers looking for?",
+ ),
+ ]
+
+ # update the mock questions with the questions
+ mock_lemur_answer["response"][0]["question"] = questions[0].question
+ mock_lemur_answer["response"][1]["question"] = questions[1].question
+
+ # mock the specific endpoints
+ httpx_mock.add_response(
+ url=f"{aai.settings.base_url}{ENDPOINT_LEMUR}/question-answer",
+ status_code=httpx.codes.OK,
+ method="POST",
+ json=mock_lemur_answer,
+ )
+
+ # test input_text input
+ # mimic the usage of the SDK
+ lemur = aai.Lemur()
+ result = lemur.question(
+ questions, input_text="This transcript is a test transcript."
+ )
+ assert isinstance(result, aai.LemurQuestionResponse)
+
+ answers = result.response
+ # check whether answers is a list
+ assert isinstance(answers, list)
+
+ # check the response
+ for idx, answer in enumerate(answers):
+ assert answer.question == mock_lemur_answer["response"][idx]["question"]
+ assert answer.answer == mock_lemur_answer["response"][idx]["answer"]
+
+ # check whether we mocked everything
+ assert len(httpx_mock.get_requests()) == 1
+
+
def test_lemur_question_fails(httpx_mock: HTTPXMock):
"""
Tests whether asking a question fails.
@@ -149,7 +249,7 @@ def test_lemur_question_fails(httpx_mock: HTTPXMock):
assert len(httpx_mock.get_requests()) == 1
-def test_lemur_summarize_succeeds(httpx_mock: HTTPXMock):
+def test_lemur_summarize_succeeds_transcript(httpx_mock: HTTPXMock):
"""
Tests whether summarizing a transcript via LeMUR succeeds.
"""
@@ -184,6 +284,41 @@ def test_lemur_summarize_succeeds(httpx_mock: HTTPXMock):
assert len(httpx_mock.get_requests()) == 1
+def test_lemur_summarize_succeeds_input_text(httpx_mock: HTTPXMock):
+ """
+ Tests whether summarizing a transcript via LeMUR succeeds with input text.
+ """
+
+ # create a mock response of a LemurSummaryResponse
+ mock_lemur_summary = factories.generate_dict_factory(
+ factories.LemurSummaryResponse
+ )()
+
+ # mock the specific endpoints
+ httpx_mock.add_response(
+ url=f"{aai.settings.base_url}{ENDPOINT_LEMUR}/summary",
+ status_code=httpx.codes.OK,
+ method="POST",
+ json=mock_lemur_summary,
+ )
+
+ # test input_text input
+ lemur = aai.Lemur()
+ result = lemur.summarize(
+ context="Callers asking for cars", answer_format="TLDR", input_text="Test test"
+ )
+
+ assert isinstance(result, aai.LemurSummaryResponse)
+
+ summary = result.response
+
+ # check the response
+ assert summary == mock_lemur_summary["response"]
+
+ # check whether we mocked everything
+ assert len(httpx_mock.get_requests()) == 1
+
+
def test_lemur_summarize_fails(httpx_mock: HTTPXMock):
"""
Tests whether summarizing a transcript via LeMUR fails.
@@ -209,7 +344,7 @@ def test_lemur_summarize_fails(httpx_mock: HTTPXMock):
assert len(httpx_mock.get_requests()) == 1
-def test_lemur_action_items_succeeds(httpx_mock: HTTPXMock):
+def test_lemur_action_items_succeeds_transcript(httpx_mock: HTTPXMock):
"""
Tests whether generating action items for a transcript via LeMUR succeeds.
"""
@@ -247,6 +382,43 @@ def test_lemur_action_items_succeeds(httpx_mock: HTTPXMock):
assert len(httpx_mock.get_requests()) == 1
+def test_lemur_action_items_succeeds_input_text(httpx_mock: HTTPXMock):
+ """
+ Tests whether generating action items for a transcript via LeMUR succeeds.
+ """
+
+ # create a mock response of a LemurActionItemsResponse
+ mock_lemur_action_items = factories.generate_dict_factory(
+ factories.LemurActionItemsResponse
+ )()
+
+ # mock the specific endpoints
+ httpx_mock.add_response(
+ url=f"{aai.settings.base_url}{ENDPOINT_LEMUR}/action-items",
+ status_code=httpx.codes.OK,
+ method="POST",
+ json=mock_lemur_action_items,
+ )
+
+ # test input_text input
+ lemur = aai.Lemur()
+ result = lemur.action_items(
+ context="Customers asking for help with resolving their problem",
+ answer_format="Three bullet points",
+ input_text="Test test",
+ )
+
+ assert isinstance(result, aai.LemurActionItemsResponse)
+
+ action_items = result.response
+
+ # check the response
+ assert action_items == mock_lemur_action_items["response"]
+
+ # check whether we mocked everything
+ assert len(httpx_mock.get_requests()) == 1
+
+
def test_lemur_action_items_fails(httpx_mock: HTTPXMock):
"""
Tests whether generating action items for a transcript via LeMUR fails.
@@ -275,7 +447,7 @@ def test_lemur_action_items_fails(httpx_mock: HTTPXMock):
assert len(httpx_mock.get_requests()) == 1
-def test_lemur_task_succeeds(httpx_mock: HTTPXMock):
+def test_lemur_task_succeeds_transcript(httpx_mock: HTTPXMock):
"""
Tests whether creating a task request succeeds.
"""
@@ -310,6 +482,38 @@ def test_lemur_task_succeeds(httpx_mock: HTTPXMock):
assert len(httpx_mock.get_requests()) == 1
+def test_lemur_task_succeeds_input_text(httpx_mock: HTTPXMock):
+ """
+ Tests whether creating a task request succeeds.
+ """
+
+ # create a mock response of a LemurSummaryResponse
+ mock_lemur_task_response = factories.generate_dict_factory(
+ factories.LemurTaskResponse
+ )()
+
+ # mock the specific endpoints
+ httpx_mock.add_response(
+ url=f"{aai.settings.base_url}{ENDPOINT_LEMUR}/task",
+ status_code=httpx.codes.OK,
+ method="POST",
+ json=mock_lemur_task_response,
+ )
+ # test input_text input
+ lemur = aai.Lemur()
+ result = lemur.task(
+ prompt="Create action items of the meeting", input_text="Test test"
+ )
+
+ # check the response
+ assert isinstance(result, aai.LemurTaskResponse)
+
+ assert result.response == mock_lemur_task_response["response"]
+
+ # check whether we mocked everything
+ assert len(httpx_mock.get_requests()) == 1
+
+
def test_lemur_ask_coach_fails(httpx_mock: HTTPXMock):
"""
Tests whether creating a task request fails.