-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
502 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
You are a branding consultant helping the user come up with potential names for their product. Based on the problem and target audience they described, suggest 5 product names that capture the essence of their product and core functionality. | ||
|
||
For each name: | ||
1. Ensure it is short and catchy (ideally 1-3 words). | ||
2. Provide a brief description of what the name means and why it fits the product. | ||
3. Match the tone of the names to the product's target audience (e.g., playful, professional, or neutral). | ||
4. Include a catchy tagline that encapsulates the essence of the product. | ||
5. Provide insight on how the name resonates with the intended target audience. | ||
6. Suggest similar names for users to consider. | ||
7. Briefly describe the branding potential of the name, including aspects like logo potential or marketability. | ||
|
||
### Expected Responses: | ||
|
||
```json | ||
{ | ||
"product_names": [ | ||
{ | ||
"product_name": "Name1", | ||
"domains": ["name1.com", "name1app.com"], | ||
"why": "A brief description of why this product name is great.", | ||
"tagline": "Catchy tagline that sums up the product.", | ||
"target_audience_insight": "This name appeals to young professionals looking for innovative solutions.", | ||
"similar_names": ["Name1Plus", "Name1Pro"], | ||
"branding_potential": "The name has strong branding potential with a memorable sound and visual appeal." | ||
}, | ||
{ | ||
"product_name": "Name2", | ||
"domains": ["name2.com", "name2app.com"], | ||
"why": "A brief description of why this product name is great.", | ||
"tagline": "A catchy tagline that captures the product's essence.", | ||
"target_audience_insight": "Appeals to tech-savvy users seeking efficiency.", | ||
"similar_names": ["Name2Lite", "Name2X"], | ||
"branding_potential": "This name could be effectively branded with modern visuals." | ||
} | ||
] | ||
} | ||
``` | ||
|
||
### Guidelines: | ||
- Friendly Tone: Use a conversational tone, as if you're chatting with a friend. | ||
- Avoid Jargon: Skip formal, sales-like language or buzzwords such as "streamline," "enhance," "tailored," "leverage," "thrilled," etc. | ||
- Ensure the language is clear, practical, and builds confidence in the product's value. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
122 changes: 122 additions & 0 deletions
122
src/idea/adapters/OpenAIService/PotentialNamesEvaluator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import OpenAI from 'openai' | ||
import { z } from 'zod' | ||
import { getPromptContent } from '@/lib/prompts' | ||
|
||
interface PotentialName { | ||
productName: string | ||
domains: string[] | ||
why: string | ||
tagline: string | ||
targetAudienceInsight: string | ||
similarNames: string[] | ||
brandingPotential: string | ||
} | ||
|
||
type Evaluation = PotentialName[] | ||
|
||
interface TargetAudience { | ||
segment: string | ||
description: string | ||
challenges: string[] | ||
} | ||
|
||
const ResponseSchema = z.object({ | ||
product_names: z.array( | ||
z.object({ | ||
product_name: z.string(), | ||
domains: z.array(z.string()), | ||
why: z.string(), | ||
tagline: z.string(), | ||
target_audience_insight: z.string(), | ||
similar_names: z.array(z.string()), | ||
branding_potential: z.string(), | ||
}) | ||
), | ||
}) | ||
|
||
export class PotentialNamesEvaluator { | ||
private readonly openai: OpenAI | ||
|
||
constructor(apiKey: string) { | ||
this.openai = new OpenAI({ | ||
apiKey: apiKey, | ||
}) | ||
} | ||
|
||
async evaluatePotentialNames( | ||
problem: string, | ||
marketExistence: string, | ||
targetAudiences: TargetAudience[] | ||
): Promise<Evaluation> { | ||
const promptContent = getPromptContent('00-product-names-analysis') | ||
|
||
if (!promptContent) { | ||
throw new Error('Prompt content not found') | ||
} | ||
|
||
const response = await this.openai.chat.completions.create({ | ||
model: 'gpt-4o-mini', | ||
messages: [ | ||
{ | ||
role: 'system', | ||
content: [ | ||
{ | ||
type: 'text', | ||
text: promptContent.trim(), | ||
}, | ||
], | ||
}, | ||
{ | ||
role: 'user', | ||
content: [ | ||
{ | ||
type: 'text', | ||
text: `Here is the problem my product aims to solve: """ | ||
${problem.trim()}""" | ||
Also I have a market existence research: """ | ||
${marketExistence.trim()}""" | ||
Here are my segments: """ | ||
${targetAudiences | ||
.map((targetAudience, idx) => { | ||
let content = '' | ||
content += `Segment ${idx + 1}: ${targetAudience.segment}\n` | ||
content += `Description: ${targetAudience.description}\n` | ||
content += `Challenges:\n${targetAudience.challenges.join('; ')}\n\n` | ||
return content | ||
}) | ||
.join('\n\n')} | ||
"""`, | ||
}, | ||
], | ||
}, | ||
], | ||
// For most factual use cases such as data extraction, and truthful Q&A, the temperature of 0 is best. | ||
// https://help.openai.com/en/articles/6654000-best-practices-for-prompt-engineering-with-the-openai-api | ||
temperature: 0.7, | ||
max_tokens: 2000, | ||
response_format: { | ||
type: 'json_object', | ||
}, | ||
}) | ||
|
||
// TODO: Store response.usage for better analysis | ||
|
||
const content = response.choices[0].message.content ?? '' | ||
|
||
const analysis = ResponseSchema.parse(JSON.parse(content)) | ||
|
||
return analysis.product_names.map((product) => ({ | ||
productName: product.product_name, | ||
domains: product.domains, | ||
why: product.why, | ||
tagline: product.tagline, | ||
targetAudienceInsight: product.target_audience_insight, | ||
similarNames: product.similar_names, | ||
brandingPotential: product.branding_potential, | ||
})) | ||
} | ||
} |
Oops, something went wrong.