ref: Allow passing custom prompts to Groq methods

Rudimentary implementation currently. Would probably ultimately help to
have a 'prompt' domain model which can be used something like this:

Prompt(type=Prompt.SUGGESTIONS).leaning("left").current(2025).area("politics").view("American")

That way it would be easy to build your own prompt.
This commit is contained in:
Marty Oehme 2025-06-10 13:13:38 +02:00
parent 84ea46f142
commit 333d825cb7
Signed by: Marty
GPG key ID: 4E535BC19C61886E
2 changed files with 57 additions and 10 deletions

View file

@ -1,9 +1,14 @@
from typing import override
from groq import Groq from groq import Groq
from prophet.config import AiConfig from prophet.config import AiConfig
from prophet.domain.improvement import Improvement
from prophet.domain.llm import LLMClient from prophet.domain.llm import LLMClient
from prophet.domain.original import Original from prophet.domain.original import Original
AVOID_SHOCKING_TURN_OF_EVENTS: bool = True
class GroqClient(LLMClient): class GroqClient(LLMClient):
config_ai: AiConfig config_ai: AiConfig
@ -15,12 +20,23 @@ class GroqClient(LLMClient):
self.config_ai = config_ai if config_ai else AiConfig.from_env() self.config_ai = config_ai if config_ai else AiConfig.from_env()
self.client = client if client else Groq(api_key=self.config_ai.API_KEY) self.client = client if client else Groq(api_key=self.config_ai.API_KEY)
def get_alternative_title_suggestions(self, original_content: str) -> str: @override
def get_alternative_title_suggestions(
self, original_content: str, custom_prompt: str | None = None
) -> str:
prompt = (
custom_prompt
if custom_prompt
else """You are a comedy writer at a satirical newspaper. Improve
on the following satirical headline. Your new headline is funny,
can involve current political events and has an edge to it. Print
only the suggestions, with one suggestion on each line."""
)
suggestions = self.client.chat.completions.create( suggestions = self.client.chat.completions.create(
messages=[ messages=[
{ {
"role": "system", "role": "system",
"content": "You are a comedy writer at a satirical newspaper. Improve on the following satirical headline. Your new headline is funny, can involve current political events and has an edge to it. Print only the suggestions, with one suggestion on each line.", "content": prompt,
}, },
{ {
"role": "user", "role": "user",
@ -34,16 +50,34 @@ class GroqClient(LLMClient):
raise ValueError raise ValueError
return suggestions_str return suggestions_str
@override
def rewrite_title( def rewrite_title(
self, original_content: str, suggestions: str | None = None self,
original_content: str,
suggestions: str | None = None,
custom_prompt: str | None = None,
) -> str: ) -> str:
prompt = (
custom_prompt
if custom_prompt
else """
You are an editor at a satirical newspaper. Improve on the following
satirical headline. For a given headline, you diligently evaluate: (1)
Whether the headline is funny; (2) Whether the headline follows a clear
satirical goal; (3) Whether the headline has sufficient substance and
bite. Based on the outcomes of your review, you pick your favorite
headline from the given suggestions and you make targeted revisions to
it. Keep the length roughly to that of the original suggestions. Your
output consists solely of the revised headline.
"""
)
if not suggestions: if not suggestions:
suggestions = self.get_alternative_title_suggestions(original_content) suggestions = self.get_alternative_title_suggestions(original_content)
winner = self.client.chat.completions.create( winner = self.client.chat.completions.create(
messages=[ messages=[
{ {
"role": "system", "role": "system",
"content": "You are an editor at a satirical newspaper. Improve on the following satirical headline. For a given headline, you diligently evaluate: (1) Whether the headline is funny; (2) Whether the headline follows a clear satirical goal; (3) Whether the headline has sufficient substance and bite. Based on the outcomes of your review, you pick your favorite headline from the given suggestions and you make targeted revisions to it. Keep the length roughly to that of the original suggestions. Your output consists solely of the revised headline.", "content": prompt,
}, },
{ {
"role": "user", "role": "user",
@ -58,21 +92,26 @@ class GroqClient(LLMClient):
raise ValueError raise ValueError
return winner_str.strip(" \"'") return winner_str.strip(" \"'")
@override
def rewrite_summary( def rewrite_summary(
self, original: Original, improved_title: str | None = None self,
original: Original,
improved_title: str | None = None,
custom_prompt: str | None = None,
) -> str: ) -> str:
prompt = (
custom_prompt
if custom_prompt
else f""" Below there is an original title and an original summary. Then follows an improved title. Write an improved summary based on the original summary which fits to the improved title. {"Do not use the phrase: 'in a surprising turn of events' or 'in a shocking turn of events.'" if AVOID_SHOCKING_TURN_OF_EVENTS else ""} Only output the improved summary.\n\nTitle:{original.title}\nSummary:{original.summary}\n---\nTitle:{improved_title}\nSummary:"""
)
if not improved_title: if not improved_title:
improved_title = self.rewrite_title(original.title) improved_title = self.rewrite_title(original.title)
no_shocking_turn: bool = True
summary = self.client.chat.completions.create( summary = self.client.chat.completions.create(
messages=[ messages=[
{ {
"role": "user", "role": "user",
"content": f""" "content": prompt,
Below there is an original title and an original summary. Then follows an improved title. Write an improved summary based on the original summary which fits to the improved title.
{"Do not use the phrase: 'in a surprising turn of events' or 'in a shocking turn of events.'" if no_shocking_turn else ""}
Only output the improved summary.\n\nTitle:{original.title}\nSummary:{original.summary}\n---\nTitle:{improved_title}\nSummary:""",
} }
], ],
model="llama-3.3-70b-versatile", model="llama-3.3-70b-versatile",

View file

@ -31,6 +31,14 @@
</div> </div>
</div> </div>
</li> </li>
<li>
<span class="fab-label">Lefty Bee</span>
<div class="option-btn fab-icon-holder">
<div class="icon">
<i class="fas fa-arrow-left"></i>
</div>
</div>
</li>
<li> <li>
<span class="fab-label">About</span> <span class="fab-label">About</span>
<div class="option-btn fab-icon-holder"> <div class="option-btn fab-icon-holder">