Skip to content

Commit

Permalink
Confirm content requirements in outline
Browse files Browse the repository at this point in the history
  • Loading branch information
JoyousJohn committed Feb 12, 2025
1 parent 743a542 commit 6cc40a9
Show file tree
Hide file tree
Showing 3 changed files with 213 additions and 85 deletions.
194 changes: 113 additions & 81 deletions js/chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,90 +113,22 @@ function nextPhase() {
]

newActivity('Confirming formatting adherence', undefined, undefined, true);
}

makeRequest(payload);
}


function addTokenUsageToActivity(usage, url, timerId) {

// alert(timerId)

let totalTime = '';
if (usage.total_time) {
totalTime = usage.total_time
} else if (usage.total_latency) {
totalTime = usage.total_latency
}
if (totalTime) {
totalTime = ' | ' + totalTime.toFixed(2) + 's'
}

let cost = '';
if (usage.estimated_cost) {
cost = usage.estimated_cost.toString().split(/(?<=\.\d*?[1-9])/)[0];
cost = ' | $' + cost
overallTokens['cost'] += usage.estimated_cost
}

overallTokens['requests']++

if (url) {
const $element = $(`.token-count[data-activity-url="${url}"]:not(.activity-error)`).first();
$element.text(usage.prompt_tokens + ' / ' + usage.completion_tokens + ' / ' + usage.total_tokens + ' tokens' + totalTime + cost);
$element.parent().find('.activity-header').removeClass('activity-understanding');
} else {
$('.token-count:not(.activity-error').first().text(usage.prompt_tokens + ' / ' + usage.completion_tokens + ' / ' + usage.total_tokens + ' tokens' + totalTime + cost);
}

if (timerId) {
// console.log(`Stopping timer with id: ${timerId}`)
stopActivityTimer(timerId);
}

if (cost) {
cost = ' $' + overallTokens['cost'].toString().split(/(?<=\.\d*?[1-9]\d)/)[0] + ' / '
}

overallTokens['input'] += usage.prompt_tokens
overallTokens['output'] += usage.completion_tokens

const current_time = new Date();
const timeDifference = current_time - stats['start_time'];
let minutes = (timeDifference / (1000 * 60));

let rpm = (overallTokens['requests']/minutes).toFixed(1)
if (rpm > overallTokens['requests']) {
rpm = overallTokens['requests']
}

let workingContext = '';
let totalWords = 0;

let memoryMapContext = ''
let memoryMapWordsLength = 0;

if (Object.keys(sources).length !== 0) {
workingContext = 0;
Object.values(sources).forEach(source => {
workingContext += source['length'];
totalWords += source['text'].split(' ').length

if (source['description']) {
memoryMapContext += source['description']
memoryMapWordsLength += source['description'].split(' ').length
}
})
workingContext = workingContext.toLocaleString()
workingContext = '<br>Source context: ' + workingContext + ` chars / ${totalWords.toLocaleString()} words`
} else if (phase === 'reviseContent') {
payload['messages'] = [
{role: "system", content: reviseContentPrompt},
{role: "user", content: `
DOCUMENT_OUTLINE: ${JSON.stringify(plan)}
CONTENT_REQUIREMENTS: ${refinedContentRequirements}`
},
{role: "assistant", content: "{"}
]

memoryMapContext = `<br> Memory map: ` + memoryMapContext.length.toLocaleString() + ` chars / ${memoryMapWordsLength.toLocaleString()} words`
newActivity('Confirming content adherence', undefined, undefined, true);

}

$('.overall-tokens').html(`${overallTokens['input'].toLocaleString()} / ${overallTokens['output'].toLocaleString()} / ${(overallTokens['input'] + overallTokens['output']).toLocaleString()} total tokens <br>${cost} ${overallTokens['requests']} request${overallTokens['requests'] !== 1 ? 's' : ''} / <span class="rpm">${rpm}</span> RPM${workingContext}${memoryMapContext}`)

makeRequest(payload);
}


Expand Down Expand Up @@ -365,24 +297,124 @@ function makeRequest(payload) {
console.log(context)

if (follows_formatting) {
setPhase('reviseContent')
newActivity('Layout conforms with formatting')
beginSearches();
nextPhase();
} else {
newActivity('Modified layout to follow formatting')
priorPlans.push(plan)
plan = context.modified_layout
nextPhase(); // iterate again
}

} else if (phase === `reviseContent`) {

addTokenUsageToActivity(usage, undefined, latestTimerId())

const meets_requirements = context.meets_requirements

console.log(context)

if (meets_requirements) {
newActivity('Layout content conforms with requirements')
beginSearches();
} else {
newActivity('Modified layout to follow content requirements')
priorPlans.push(plan)
plan = context.modified_outline
nextPhase(); // iterate again
}

} else {
// Fallback: simply add the full response to the modal
addToModalMessage(fullResponse);
}
})
.catch(error => console.error('Error:', error));
}
}



function addTokenUsageToActivity(usage, url, timerId) {

// alert(timerId)

let totalTime = '';
if (usage.total_time) {
totalTime = usage.total_time
} else if (usage.total_latency) {
totalTime = usage.total_latency
}
if (totalTime) {
totalTime = ' | ' + totalTime.toFixed(2) + 's'
}

let cost = '';
if (usage.estimated_cost) {
cost = usage.estimated_cost.toString().split(/(?<=\.\d*?[1-9])/)[0];
cost = ' | $' + cost
overallTokens['cost'] += usage.estimated_cost
}

overallTokens['requests']++

if (url) {
const $element = $(`.token-count[data-activity-url="${url}"]:not(.activity-error)`).first();
$element.text(usage.prompt_tokens + ' / ' + usage.completion_tokens + ' / ' + usage.total_tokens + ' tokens' + totalTime + cost);
$element.parent().find('.activity-header').removeClass('activity-understanding');
} else {
$('.token-count:not(.activity-error').first().text(usage.prompt_tokens + ' / ' + usage.completion_tokens + ' / ' + usage.total_tokens + ' tokens' + totalTime + cost);
}

if (timerId) {
// console.log(`Stopping timer with id: ${timerId}`)
stopActivityTimer(timerId);
}

if (cost) {
cost = ' $' + overallTokens['cost'].toString().split(/(?<=\.\d*?[1-9]\d)/)[0] + ' / '
}

overallTokens['input'] += usage.prompt_tokens
overallTokens['output'] += usage.completion_tokens

const current_time = new Date();
const timeDifference = current_time - stats['start_time'];
let minutes = (timeDifference / (1000 * 60));

let rpm = (overallTokens['requests']/minutes).toFixed(1)
if (rpm > overallTokens['requests']) {
rpm = overallTokens['requests']
}

let workingContext = '';
let totalWords = 0;

let memoryMapContext = ''
let memoryMapWordsLength = 0;

if (Object.keys(sources).length !== 0) {
workingContext = 0;
Object.values(sources).forEach(source => {
workingContext += source['length'];
totalWords += source['text'].split(' ').length

if (source['description']) {
memoryMapContext += source['description']
memoryMapWordsLength += source['description'].split(' ').length
}
})
workingContext = workingContext.toLocaleString()
workingContext = '<br>Source context: ' + workingContext + ` chars / ${totalWords.toLocaleString()} words`

memoryMapContext = `<br> Memory map: ` + memoryMapContext.length.toLocaleString() + ` chars / ${memoryMapWordsLength.toLocaleString()} words`

}

$('.overall-tokens').html(`${overallTokens['input'].toLocaleString()} / ${overallTokens['output'].toLocaleString()} / ${(overallTokens['input'] + overallTokens['output']).toLocaleString()} total tokens <br>${cost} ${overallTokens['requests']} request${overallTokens['requests'] !== 1 ? 's' : ''} / <span class="rpm">${rpm}</span> RPM${workingContext}${memoryMapContext}`)

}


function newTimerId() {
return $('.activity-header').length + 1;
Expand Down
102 changes: 99 additions & 3 deletions js/prompts.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,102 @@ Output if no changes needed:
}`


const reviseContentPrompt = `Return only a JSON object that analyzes if a document outline meets specific content requirements. You must modify the outline as needed to make it fully address ALL CONTENT_REQUIREMENTS, including changing, adding, or removing any number of sections. Any changes you describe in changes_explanation MUST be reflected in the modified_outline you return.
Input format:
1. DOCUMENT_OUTLINE: An array of section objects with the structure:
[
{
"section_title": "string: title of the section",
"description": "string: comprehensive explanation of section content",
"search_keywords": ["string: specific search term", ...]
},
...
]
2. CONTENT_REQUIREMENTS: A string containing specific content coverage requirements
Output format (return ONLY this JSON object with no additional text):
{
"meets_requirements": boolean,
// The following keys are only included if content changes were required:
"modified_outline": [
{
"section_title": "string: section title",
"description": "string: section description addressing requirements",
"search_keywords": ["string: relevant search terms", ...]
},
...
],
"changes_explanation": "string: detailed explanation of all content changes made to meet requirements",
"requirements_verification": ["string: explanation of how each content requirement is addressed", ...]
}
Rules:
- You MUST analyze if the outline addresses ALL elements specified in CONTENT_REQUIREMENTS
- You MUST modify the outline to fully cover missing or inadequately addressed requirements by:
- Adding new sections for missing content
- Expanding existing sections to cover requirements more thoroughly
- Removing redundant or irrelevant sections
- Merging or splitting sections to better organize required content
- Adding specific data points or analyses needed
- The modified_outline you return MUST exactly match the changes you describe in changes_explanation
- The requirements_verification list MUST explicitly show how each content requirement is addressed
- If DOCUMENT_OUTLINE fully meets CONTENT_REQUIREMENTS:
Return: { "meets_requirements": true }
- If any content requirements are not met:
Return: {
"meets_requirements": false,
"modified_outline": [fully corrected outline matching your changes_explanation],
"changes_explanation": "explanation of changes that exactly match your modified_outline",
"requirements_verification": ["verification of each requirement's coverage"]
}
Example:
Input:
{
"DOCUMENT_OUTLINE": [
{
"section_title": "Market Overview",
"description": "General discussion of current market conditions",
"search_keywords": ["market", "overview"]
}
],
"CONTENT_REQUIREMENTS": "Must include 5-year market forecast, competitive analysis with market shares, and regulatory impact assessment"
}
Output if changes needed:
{
"meets_requirements": false,
"modified_outline": [
{
"section_title": "Market Overview and Forecast",
"description": "Analysis of current market conditions and detailed 5-year growth projections",
"search_keywords": ["market", "overview", "forecast", "growth"]
},
{
"section_title": "Competitive Landscape",
"description": "Comprehensive analysis of market shares and competitive positioning of key players",
"search_keywords": ["competition", "market share", "competitors"]
},
{
"section_title": "Regulatory Analysis",
"description": "Assessment of current regulations and their impact on market development",
"search_keywords": ["regulations", "compliance", "impact"]
}
],
"changes_explanation": "Added forecast component to Market Overview, created new Competitive Landscape section for market share analysis, added Regulatory Analysis section",
"requirements_verification": [
"5-year forecast integrated into Market Overview and Forecast section",
"Competitive analysis with market shares covered in new Competitive Landscape section",
"Regulatory impact assessed in dedicated Regulatory Analysis section"
]
}
Output if no changes needed:
{
"meets_requirements": true
}
`


const categorizeSourcePrompt = `You will be provided a large body of text. Your task is to return a string sufficiently describing what the content within the text is and contains. Be extremely detailed and thorough; cover all the info covered in the text, but do not explain its purpose. The end goal is categorize this text based on its description of its contents.
Expand Down Expand Up @@ -346,7 +442,7 @@ Important: Do *NOT* add any comments.
Example response:
{
"source_ids": [1, 2, 3, 4, 7, 9], (List of most relevant source IDs, maximum of 20)
"source_ids": [SRC_1, SRC_2, SRC_3, SRC_4, SRC_7, SRC_9], (List of most relevant source IDs, maximum of 20)
"required_info_description": "string", (Only include if information is missing)
"search_term": "string" (Only include if information is missing)
}
Expand Down Expand Up @@ -384,7 +480,7 @@ Evaluation Process:
Requirements:
- Return a JSON object containing only the source_ids key
- The source_ids value should be an array of up to 20 numerical IDs
- The source_ids value should be an array of up to 20 source ID strings
- IDs should be ordered by relevance/importance
Important formatting rules:
Expand All @@ -396,7 +492,7 @@ Important formatting rules:
- Do not return any notes or comments
Example response:
{"source_ids":[1,2,3,4,7,9]}
{"source_ids":[SRC_1, SRC_2, SRC_3, SRC_4, SRC_7, SRC_9]}
Before finalizing response:
- Verify that the most critical sources are included
Expand Down
2 changes: 1 addition & 1 deletion js/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ async function beginSearches() {
// add that this only runs if the initial relevantAndNeededSources returned it has enough and didn't need to run. oteherwise checking if we have the relevant sources happens twice on the same source ocuments data info.
relevantAndNeededSources = await getRelevantAndNeededSources(section.description, true)

const required_source_ids = relevantAndNeededSources.source_ids.slice(0, 20)
let required_source_ids = relevantAndNeededSources.source_ids.slice(0, 20).map(id => id.split('_')[1]);

newActivity(`Using ${required_source_ids.length} sources`)

Expand Down

0 comments on commit 6cc40a9

Please sign in to comment.