Skip to content

Commit a0dde88

Browse files
committed
feat: Implement OpenAI client and validation utilities
- Added OpenAI client initialization with API key validation. - Created validation utility for OpenAI chat completions using Zod schema. - Developed complete post analysis functionality, integrating title generation, categorization, and sentiment analysis. - Implemented Redis post group management with title and sentiment summary generation. - Added Redis client initialization and connection handling with error management. - Created deduplication listener for posts using cosine similarity on embeddings. - Seeded Redis database with mock data and provided command-line interface for seeding operations. - Added embedding retrieval with retry logic for OpenAI API calls.
1 parent 4ec8528 commit a0dde88

20 files changed

+417
-135
lines changed

run-classifier.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#!/usr/bin/env node
22

3-
import { runCompleteAnalysisDemo } from './src/completePostAnalysis.js';
4-
import { runCategorization } from './src/classifyWithOpenAI.js';
5-
import { analyzeMultiplePosts } from './src/analyzeSentiment.js';
6-
import { generateTitlesForPosts } from './src/generateTitle.js';
3+
import { runCompleteAnalysisDemo } from './src/post/completePostAnalysis.js';
4+
import { runCategorization } from './src/openai/classifyWithOpenAI.js';
5+
import { analyzeMultiplePosts } from './src/analysis/analyzeSentiment.js';
6+
import { generateTitlesForPosts } from './src/analysis/generateTitle.js';
77

88
// Get command line argument
99
const command = process.argv[2];

src/analyzeSentiment.ts renamed to src/analysis/analyzeSentiment.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
// This file has been moved to the analysis subfolder.
2+
// Please update your imports accordingly.
3+
import { analyzeMultiplePosts } from './analyzeSentiment.js';
14
import type OpenAI from 'openai';
2-
import openai from './openaiClient.js';
3-
import { callOpenAIWithValidation } from './openaiValidationUtil.js';
5+
import openai from '../openai/openaiClient.js';
6+
import { callOpenAIWithValidation } from '../openai/openaiValidationUtil.js';
47
import { z } from 'zod';
58
import { generateTitleForPost } from './generateTitle.js';
69

src/generateTitle.ts renamed to src/analysis/generateTitle.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
// This file has been moved to the analysis subfolder.
2+
// Please update your imports accordingly.
3+
import { generateTitleForPost } from './generateTitle.js';
14
import type OpenAI from 'openai';
2-
import openai from './openaiClient.js';
3-
import { callOpenAIWithValidation } from './openaiValidationUtil.js';
5+
import openai from '../openai/openaiClient.js';
6+
import { callOpenAIWithValidation } from '../openai/openaiValidationUtil.js';
47
import { z } from 'zod';
58

69
// Title generation result type

src/constants.ts renamed to src/lib/constants.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// This file has been moved to the analysis subfolder.
2+
// Please update your imports accordingly.
3+
export const CATEGORIES = [...]; // Keep the original content
14
// src/constants.ts
25

36
export const CATEGORIES = [

src/classifyWithOpenAI.ts renamed to src/openai/classifyWithOpenAI.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
// This file has been moved to the analysis subfolder.
2+
// Please update your imports accordingly.
3+
import { categorizePost } from './analysis/classifyWithOpenAI.js';
14
// No top-level execution. Export the runner and allow explicit CLI invocation with --run.
25
import type OpenAI from 'openai';
36
import type { ChatCompletionMessageParam } from 'openai/resources';
47
import openai from './openaiClient.js';
58
import { callOpenAIWithValidation } from './openaiValidationUtil.js';
69
import { z } from 'zod';
7-
import { generateTitleForPost } from './generateTitle.js';
8-
import { CATEGORIES } from './constants.js';
10+
import { generateTitleForPost } from '../analysis/generateTitle.js';
11+
import { CATEGORIES } from '../lib/constants.js';
912

1013
// Zod schema for categorization validation
1114
const CategorizationSchema = z.object({
File renamed without changes.

src/openaiValidationUtil.ts renamed to src/openai/openaiValidationUtil.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
// This file has been moved to the analysis subfolder.
2+
// Please update your imports accordingly.
3+
import { callOpenAIWithValidation } from './analysis/openaiValidationUtil.js';
14
import type OpenAI from 'openai';
25
import type { ChatCompletionMessageParam } from 'openai/resources';
36
import { ZodSchema } from 'zod';
4-
import { sleep, jitteredBackoff } from './lib/utils.js';
7+
import { sleep, jitteredBackoff } from '../lib/utils.js';
58

69
/**
710
* Calls OpenAI chat completion API and validates the response with a Zod schema, retrying up to maxAttempts times.

src/completePostAnalysis.ts renamed to src/post/completePostAnalysis.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
// This file has been moved to the analysis subfolder.
2+
// Please update your imports accordingly.
3+
import { analyzeCompletePost } from './analysis/completePostAnalysis.js';
14
import type OpenAI from 'openai';
2-
import openai from './openaiClient.js';
3-
import { categorizePost, type Categorization } from './classifyWithOpenAI.js';
4-
import { analyzeMultiplePosts, type SentimentResult } from './analyzeSentiment.js';
5-
import { generateTitleForPost, type TitleResult } from './generateTitle.js';
5+
import openai from '../openai/openaiClient.js';
6+
import { categorizePost, type Categorization } from '../openai/classifyWithOpenAI.js';
7+
import { analyzeMultiplePosts, type SentimentResult } from '../analysis/analyzeSentiment.js';
8+
import { generateTitleForPost, type TitleResult } from '../analysis/generateTitle.js';
69

710
// Combined result type for complete post analysis
811
export type PostAnalysisResult = {

src/postGroup.ts renamed to src/redis/postGroup.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import cron from 'node-cron';
2-
import { generateTitleForPost, generateSentimentSummariesForGroup, type SentimentSummaries } from './generateTitle';
2+
import { generateTitleForPost, generateSentimentSummariesForGroup, type SentimentSummaries } from '../analysis/generateTitle';
33
import { initRedis, getRedisClient } from './redisClient';
44

55
export type Post = {

src/redis/redisCheck.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { initRedis } from './redis/redisClient.js';
2+
3+
async function checkRedisSeed() {
4+
const client = await initRedis();
5+
try {
6+
const posts = JSON.parse((await client.get('posts')) || '[]');
7+
console.log(JSON.stringify(posts));
8+
} catch (err) {
9+
console.error('Error checking Redis seed:', err);
10+
} finally {
11+
await client.disconnect();
12+
}
13+
}
14+
15+
checkRedisSeed();
16+
import { initRedis } from './redisClient.js';
17+
18+
async function checkRedisSeed() {
19+
const client = await initRedis();
20+
try {
21+
const posts = JSON.parse((await client.get('posts')) || '[]');
22+
console.log(JSON.stringify(posts));
23+
} catch (err) {
24+
console.error('Error checking Redis seed:', err);
25+
} finally {
26+
await client.disconnect();
27+
}
28+
}
29+
30+
checkRedisSeed();

0 commit comments

Comments
 (0)