mirror of
https://github.com/technovangelist/videoprojects.git
synced 2026-09-10 07:16:19 -04:00
add no framework agent
This commit is contained in:
parent
8f914f4f5a
commit
4803ed39db
BIN
2024-05-31-agentframeworks/bun.lockb
Executable file
BIN
2024-05-31-agentframeworks/bun.lockb
Executable file
Binary file not shown.
16
2024-05-31-agentframeworks/package.json
Normal file
16
2024-05-31-agentframeworks/package.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "noframeworkagents",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dirty-json": "^0.9.2",
|
||||
"ollama": "^0.5.1",
|
||||
"readline": "^1.3.0"
|
||||
}
|
||||
}
|
||||
5
2024-05-31-agentframeworks/prompts.ts
Normal file
5
2024-05-31-agentframeworks/prompts.ts
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
export const titleprompt = "You will be given a topic, a description, and a list of high performing titles for a similar topic. Create 10 potential titles for this video topic and description. It is very important to use the list of videos to help you generate the titles. The titles should be less than 70 characters and should have a high click-through-rate."
|
||||
|
||||
export const descriptionprompt = "Create a great description for a video based on the information provided by the user. This description will be add to the video on YouTube when it is submitted. The description should be 200 to 500 words. At the end, include something convincing to encourage the user to subscribe to the newsletter at technovangelist.com\/newsletter, and to join the Patreon at patreon.com\/technovangelist."
|
||||
|
||||
export const announcementprompt = "Every time I have a new video, I like to send out an email to my subscribers. Please create an email to send to that list based on the topic and description provided by the user. The email should be 300 to 600 words and include a place for the subscriber\'s name, what the viewer will learn from the video, and a link to the video that will render in an email. also encourage the reader to sign up for my patreon if they want to support me further. The email should be signed off from me, Matt Williams."
|
||||
27
2024-05-31-agentframeworks/tsconfig.json
Normal file
27
2024-05-31-agentframeworks/tsconfig.json
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
// Enable latest features
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleDetection": "force",
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
|
||||
// Bundler mode
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
|
||||
// Best practices
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
|
||||
// Some stricter flags (disabled by default)
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noPropertyAccessFromIndexSignature": false
|
||||
}
|
||||
}
|
||||
108
2024-05-31-agentframeworks/videoSearchTool.ts
Normal file
108
2024-05-31-agentframeworks/videoSearchTool.ts
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
import * as readline from "readline/promises";
|
||||
|
||||
type VideoSearchResults = {
|
||||
id: string;
|
||||
title: string;
|
||||
channelId: string;
|
||||
channelTitle: string;
|
||||
daysSincePublished: number;
|
||||
}
|
||||
|
||||
type VideoDetails = {
|
||||
videoString: string;
|
||||
title: string;
|
||||
viewCount: number;
|
||||
likeCount: number;
|
||||
commentCount: number;
|
||||
subscriberCount: number;
|
||||
score: number;
|
||||
}
|
||||
|
||||
const getInput = async (question: string): Promise<string> => {
|
||||
let output = "";
|
||||
const rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
});
|
||||
output = await rl.question(question);
|
||||
rl.close();
|
||||
return output;
|
||||
}
|
||||
|
||||
export const getTopic = async (): Promise<string> => {
|
||||
const topic = await getInput("Enter a topic to search for: ");
|
||||
return topic;
|
||||
}
|
||||
|
||||
export const getDetails = async (topic: string): Promise<string> => {
|
||||
const details = await getInput(`Enter a description for the video on ${topic}: `);
|
||||
return details;
|
||||
}
|
||||
|
||||
export const videoSearchTool = async (topic: string, maxResults: number = 35): Promise<VideoSearchResults[]> => {
|
||||
|
||||
const results: VideoSearchResults[] = [];
|
||||
topic = encodeURIComponent(topic);
|
||||
const apiKey = Bun.env.YouTubeAPIKey;
|
||||
const url = `https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=${maxResults}&q=${topic}&type=video&key=${apiKey}`;
|
||||
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.items) {
|
||||
for (const item of data.items) {
|
||||
const id = item.id.videoId;
|
||||
const title = item.snippet.title;
|
||||
const channelId = item.snippet.channelId;
|
||||
const channelTitle = item.snippet.channelTitle;
|
||||
const daysSincePublished = Math.floor((new Date().getTime() - new Date(item.snippet.publishedAt.slice(0, 10)).getTime())/(1000*60*60*24));
|
||||
|
||||
results.push({
|
||||
id,
|
||||
title,
|
||||
channelId,
|
||||
channelTitle,
|
||||
daysSincePublished,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
export const videoDetailsTool = async (video: VideoSearchResults): Promise<VideoDetails> => {
|
||||
|
||||
}
|
||||
|
||||
const apiKey = Bun.env.YouTubeAPIKey;
|
||||
const videoUrl = `https://www.googleapis.com/youtube/v3/videos?part=snippet,statistics&id=${video.id}&key=${apiKey}`;
|
||||
const channelUrl = `https://www.googleapis.com/youtube/v3/channels?part=statistics&id=${video.channelId}&key=${apiKey}`;
|
||||
|
||||
const videoResponse = await fetch(videoUrl);
|
||||
const channelResponse = await fetch(channelUrl);
|
||||
|
||||
const videoData = await videoResponse.json();
|
||||
const channelData = await channelResponse.json();
|
||||
|
||||
const title = videoData.items[0].snippet.title;
|
||||
const viewCount = (videoData.items[0].statistics.viewCount as number);
|
||||
const likeCount = videoData.items[0].statistics.likeCount;
|
||||
const commentCount = videoData.items[0].statistics.commentCount;
|
||||
const subscriberCount = channelData.items[0].statistics.subscriberCount;
|
||||
|
||||
const videoString = ` - Title: ${title}\n - Channel: ${video.channelTitle}\n - View Count: ${Number(viewCount).toLocaleString()}\n - Days Since Published: ${video.daysSincePublished}\n - Likes: ${Number(likeCount).toLocaleString()}\n - Subscriber Count: ${Number(subscriberCount).toLocaleString('en-US')}\n - Video URL: https://www.youtube.com/watch?v=${video.id}\n`;
|
||||
|
||||
// const score = (viewCount / video.daysSincePublished / subscriberCount) + (likeCount * 10) + (commentCount * 100);
|
||||
const score = (((viewCount / subscriberCount) * 0.4) + ((likeCount / viewCount) * 0.3) + ((commentCount / viewCount) * 0.2) * (1/video.daysSincePublished)) ;
|
||||
|
||||
return {
|
||||
videoString,
|
||||
title,
|
||||
viewCount,
|
||||
likeCount,
|
||||
commentCount,
|
||||
subscriberCount,
|
||||
score
|
||||
};
|
||||
|
||||
}
|
||||
58
2024-05-31-agentframeworks/ytresearch.ts
Normal file
58
2024-05-31-agentframeworks/ytresearch.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
import ollama from "ollama";
|
||||
import * as djson from "dirty-json";
|
||||
import { getTopic, getDetails, videoSearchTool, videoDetailsTool } from "./videoSearchTool.ts";
|
||||
import { titleprompt, descriptionprompt, announcementprompt } from "./prompts.ts";
|
||||
|
||||
// const topic = await getTopic();
|
||||
// const details = await getDetails(topic);
|
||||
const topic = "ai models local ollama"
|
||||
const details = "You are going to create a new model for ollama. use the modelfile to create an AI model in creative ways and do interesting things using parameters, system prompt, and more.";
|
||||
|
||||
const videos = await videoSearchTool(topic, 50)
|
||||
let scoredVideos = []
|
||||
for (const video of videos) {
|
||||
const videodetails = await videoDetailsTool(video);
|
||||
scoredVideos.push(videodetails);
|
||||
}
|
||||
|
||||
scoredVideos = scoredVideos.sort((a, b) => b.score - a.score).slice(0, 15);
|
||||
scoredVideos.forEach((video, index) => {
|
||||
console.log(`Video ${index + 1}: ${video.score}`);
|
||||
console.log(video.videoString)
|
||||
});
|
||||
|
||||
const rawtitlelist = await ollama.generate({
|
||||
model: "llama3",
|
||||
system: titleprompt,
|
||||
format: "json",
|
||||
prompt: `topic: ${topic}\nDescription: ${details}\nSuccessful titles:\n${scoredVideos.map(video => video.title).join("\n")}. Output as JSON, using this template: {titles: ['title1', 'title2']}`,
|
||||
})
|
||||
const titlelist = JSON.parse(rawtitlelist.response);
|
||||
|
||||
console.log(`Successful Titles for the topic: ${topic}\n\n${titlelist.titles.map((s: string) => `- ${s}`).join("\n")}\n\n`);
|
||||
|
||||
const rawnewdescription = await ollama.generate({
|
||||
model: "llama3",
|
||||
system: descriptionprompt,
|
||||
format: "json",
|
||||
prompt: ` topic: ${topic}\nDescription: ${details}\n Output as JSON, using this template: \n\n{'output': 'description of the video'} `
|
||||
});
|
||||
const newdescription = djson.parse(rawnewdescription.response).output;
|
||||
console.log(`Description for the video based on: ${details}\n${newdescription}\n\n`);
|
||||
|
||||
const rawemail = await ollama.generate({
|
||||
model: "llama3",
|
||||
system: announcementprompt,
|
||||
format: "json",
|
||||
prompt: `topic: ${topic}\nDescription: ${newdescription}\nOutput as JSON, using this template: \n{'output': 'text of the email'}`,
|
||||
});
|
||||
const email = djson.parse(rawemail.response).output;
|
||||
|
||||
console.log(`Email for the video based on the generated description: \n${email}\n\n`);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in a new issue