Skip to content

Commit

Permalink
feat: add more detail to the analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
darraghoriordan committed Sep 27, 2023
1 parent 1351494 commit 1a811ee
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 33 deletions.
9 changes: 6 additions & 3 deletions src/app/MarketingWeek/Calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,12 @@ export default function Calendar({
const startDegree = calculateTimeDegree(
item.increment.startDate,
)
const spanDegree =
let spanDegree =
calculateTimeDegree(item.increment.endDate) - startDegree

// if the span degree is less than 30 mins i'ts too hard to read. so set that as a floor
if (spanDegree < 6) {
spanDegree = 6
}
return (
<li
className="relative flex mt-px"
Expand All @@ -245,7 +248,7 @@ export default function Calendar({
key={index}
>
<ScheduledItem
item={item.raw.analysis.summary}
item={item}
onClick={() => {
setSelectedIncrement(item)
setOpenDateActions(true)
Expand Down
38 changes: 24 additions & 14 deletions src/app/MarketingWeek/Components/ScheduleItem.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,40 @@
/* eslint-disable jsx-a11y/anchor-is-valid */
import { CategoryEnum } from '../../../electron/devHistory/services/openai-service'
import { AtSymbolIcon, PencilSquareIcon } from '@heroicons/react/24/outline'
import { IncrementAnalysis } from '../../../electron/devHistory/models/IncrementAnalysis'
import { colorMap, defaultColor } from './colorMap'

export function ScheduledItem({
item,
onClick,
}: {
item: { category: CategoryEnum; text: string }
item: IncrementAnalysis
onClick: () => void
}) {
const color = colorMap.get(item.category) || defaultColor
const cat = item.raw.analysis?.summary?.category || 'other'
const text = item.summary
const hasBlogPosts = item.raw.analysis?.blogPosts?.length || 0
const hasTweets = item.raw.analysis?.tweets?.length || 0
const color = colorMap.get(cat) || defaultColor

return (
<button
onClick={onClick}
className={`absolute flex flex-col p-2 overflow-y-auto text-xs rounded-lg group inset-1 ${color.bg} leading-5 ${color.bgDark}`}
className={`absolute flex flex-col p-2 overflow-y-auto text-xs rounded-lg group inset-1 ${color.textDark} ${color.bg} leading-5 ${color.bgDark}`}
>
{/* <p className={`order-1 font-semibold ${color.textDark}`}>
{item.category}
</p> */}
<p className={`order-1 ${color.text} ${color.hoverTextDark}`}>
<span className={`font-semibold ${color.textDark}`}>
{'[ '}
{item.category} {' ] - '}
</span>
{item.text}
</p>
<div className="flex gap-x-3 items-center inline">
<p className={`font-semibold`}>{`[ ${cat}`}</p>
{hasBlogPosts ? (
<PencilSquareIcon
title="click to view blog posts"
className="w-3 h-3"
/>
) : null}
{hasTweets ? (
<AtSymbolIcon title="click to view tweets" className="w-3 h-3" />
) : null}{' '}
<p className={`font-semibold `}> {'] - '}</p>
</div>
<p className={`${color.text} ${color.hoverTextDark}`}>{text}</p>
</button>
)
}
14 changes: 11 additions & 3 deletions src/app/MarketingWeek/MarketingWeekScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ export function MarketingWeekScreen() {
e.preventDefault()
logAMessage({ message: 'Refresh Clicked', level: 'info' })
}

const sumOfBlogPosts = data?.analysis.reduce((acc, cur) => {
return acc + (cur?.raw?.analysis?.blogPosts?.length || 0)
}, 0)
const sumOfTweets = data?.analysis.reduce((acc, cur) => {
return acc + (cur?.raw?.analysis?.tweets?.length || 0)
}, 0)
control = (
<div className="flex flex-col h-[70vh]">
<header className="flex items-center justify-between flex-none py-4 border-b border-gray-200">
Expand All @@ -53,11 +60,12 @@ export function MarketingWeekScreen() {
</div>
<div className="justify-between ml-8 text-sm">
<div className="flex items-center">
<AtSymbolIcon className="w-4 h-4 mr-3" /> 0 Potential Tweets/Posts
<AtSymbolIcon className="w-4 h-4 mr-3" /> {sumOfTweets} Potential
Tweets/Posts
</div>
<div className="flex items-center">
<PencilSquareIcon className="w-4 h-4 mr-3" /> 0 Potential Blog
Posts
<PencilSquareIcon className="w-4 h-4 mr-3" /> {sumOfBlogPosts}{' '}
Potential Blog Posts
</div>
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/electron/devHistory/models/IncrementAnalysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { z } from 'zod'
export const IncrementAnalysisSchema = z.object({
increment: DateRangeSchema,
summary: z.string().or(z.undefined()),
blogPosts: z.array(z.string()),
tweets: z.array(z.object({ text: z.string() })),
raw: z.object({
events: z.array(HistoryEntrySchema),
analysis: z.optional(IncrementGPTResponseSchema),
Expand Down
6 changes: 6 additions & 0 deletions src/electron/devHistory/services/day-analyser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ export async function analyseDay(date: Date) {
return {
increment: increment,
summary: undefined,
blogPosts: [],
tweets: [],
raw: {
events: eventsForPeriod,
analysis: undefined,
Expand All @@ -109,6 +111,10 @@ export async function analyseDay(date: Date) {
return {
increment: increment,
summary: chatResult.summary?.text,
// these are intentionally empty for now
// they will be filled with combinations of the entire set of events
blogPosts: [],
tweets: [],
raw: {
events: eventsForPeriod,
analysis: chatResult,
Expand Down
62 changes: 49 additions & 13 deletions src/electron/devHistory/services/openai-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ export const IncrementGPTResponseSchema = z.object({
tokensUsed: z.number(),
errorMessage: z.string().optional(),
finishReason: z.string().optional(),
tweets: z.array(
z.object({
text: z.string(),
}),
),
blogPosts: z.array(
z.object({
text: z.string(),
}),
),
summary: z
.object({
text: z.string(),
Expand Down Expand Up @@ -59,7 +69,7 @@ export async function runChatCompletion(
const browserHistoryItems = request.historyItems
.filter(x => x.type === 'browser history')
.map(x => x.metadata)
const socialMedia = []

const completedSummaries = []
if (browserHistoryItems.length > 0) {
completedSummaries.push(
Expand All @@ -71,8 +81,9 @@ export async function runChatCompletion(
.map(x => x.metadata)

if (codeHistoryItems.length > 0) {
socialMedia.push(runSocialMediaPostsCompletion(codeHistoryItems, openai))
completedSummaries.push(runCodeDiffCompletion(codeHistoryItems, openai))
const codeDiffCompletion = runCodeDiffCompletion(codeHistoryItems, openai)

completedSummaries.push(codeDiffCompletion)
}
const allSummaries = await Promise.all(completedSummaries)
if (allSummaries.length === 1) {
Expand All @@ -97,6 +108,8 @@ export async function runChatCompletion(
return {
tokensUsed: tokensUsed,
summary: undefined,
tweets: [],
blogPosts: [],
finishReason,
errorMessage,
}
Expand All @@ -107,6 +120,12 @@ async function runCombinationSummaryCompletion(
responses: IncrementGPTResponse[],
openai: OpenAI,
): Promise<IncrementGPTResponse> {
if (responses.length === 1) {
return responses[0]
}
if (responses.length <= 0) {
throw new Error('No responses to combine')
}
const chatMessages: ChatMessage[] = [
{
role: 'user',
Expand Down Expand Up @@ -142,6 +161,8 @@ async function runCombinationSummaryCompletion(
return {
tokensUsed: completion.usage?.total_tokens || 0,
finishReason: completion.choices[0].finish_reason,
tweets: responses.flatMap(x => x.tweets),
blogPosts: responses.flatMap(x => x.blogPosts),
summary: { text: extractedSummary, category: 'software-development' },
}
}
Expand All @@ -160,12 +181,14 @@ async function runCodeDiffCompletion(
Given the tasks completed above by a software engineer on their computer, you will write their report for a standup meeting. The standup is a very short meeting so be terse.
Standup meeting report format is "What I did"
The Standup meeting report format describes what was done and why.
Guidelines:
- only return the stand up meeting report
- don't explain your answer
- don't use "stand up report:" or a descriptor like that. just return the report.
- be terse
- make sure to talk about any git code diffs`,
- make sure to talk about any git code diffs if they are provided, but don't mention this if there are no diffs provided to you`,
},
]
const model = selectBestModel(chatMessages)
Expand All @@ -181,9 +204,16 @@ async function runCodeDiffCompletion(
throw new Error(`No summary generated`)
}

const socialMediaCompletion = await runSocialMediaPostsCompletion(
codeHistoryItems,
openai,
)
return {
tokensUsed: completion.usage?.total_tokens || 0,
tokensUsed:
(completion.usage?.total_tokens || 0) + socialMediaCompletion?.tokensUsed,
finishReason: completion.choices[0].finish_reason,
blogPosts: socialMediaCompletion.blogPosts,
tweets: socialMediaCompletion.tweets,
summary: { text: extractedSummary, category: 'software-development' },
}
}
Expand All @@ -194,7 +224,7 @@ export async function runSocialMediaPostsCompletion(
const chatMessages: ChatMessage[] = [
{
role: 'user',
content: `Browsing History Session: ${JSON.stringify(historyItems)}
content: `Git Code changes: ${JSON.stringify(historyItems)}
Given the code changes completed above by a software engineer on their computer, you will generate 3 tweets for a technical audience.
Expand All @@ -203,7 +233,7 @@ Perform the following steps
2. identify tricky sections
3. write tweets about the code
examples of topics for tweets:
examples of good topics for tweets:
- the libraries, tools and frameworks used and how they helped
- the benefit of overall change
- the number of lines added or removed if significant
Expand All @@ -212,6 +242,9 @@ examples of topics for tweets:
- change is forward progress
- the importance of testing if any
- thanking everyone who helped (not just the author)
- a question e.g. a question about anyone else who has done something similar
- or a question about how to improve the code
- or a question about how to improve the process
guidelines:
- do not explain your answer
Expand Down Expand Up @@ -246,13 +279,14 @@ guidelines:
chatMessages.push({
role: 'user',
content: `
now write a long form blog post about the code changes. The audience is technical.
now write a long form blog post about the code changes. The audience is technical but it's ok to do some product marketing also.
- Write a compelling introduction
- Talk about why the change was nessecary
- describe details about the code change
- Write a conclusion
- Talk about why the change was necessary but don't oversell it
- describe details about the actual code change
- Write a short conclusion
Write a title and meta description that is optimizer for google search SEO
Write a title and meta description that are optimized for google search SEO
Output everything in markdown format`,
})
Expand Down Expand Up @@ -326,6 +360,8 @@ Guidelines:
return {
tokensUsed: categoryCompletion.usage?.total_tokens || 0,
finishReason: completion.choices[0].finish_reason,
tweets: [],
blogPosts: [],
summary: {
text: extractedSummary,
category: (extractedCategory || 'other') as CategoryEnum, // kinda hacky
Expand Down

0 comments on commit 1a811ee

Please sign in to comment.