Skip to content

Commit

Permalink
Merge pull request #11 from autonomys/project-refactor
Browse files Browse the repository at this point in the history
Refactor auto-content-creator
  • Loading branch information
jfrank-summit authored Oct 26, 2024
2 parents 01fcd41 + 9e46c9c commit d278d13
Show file tree
Hide file tree
Showing 21 changed files with 4,773 additions and 490 deletions.
1 change: 1 addition & 0 deletions auto-content-creator/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ AGENTS_PORT=3000
BACKEND_PORT=8000
FRONTEND_PORT=3030
OPENAI_API_KEY=<your_openai_api_key_here>
SERPAPI_API_KEY=<your_serpapi_api_key_here>
BACKEND_SERVICE_URL=http://localhost:8000
38 changes: 38 additions & 0 deletions auto-content-creator/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Dependencies
node_modules
.pnp
.pnp.js

# Build outputs
dist
build
out

# Environment files
.env
.env.local
.env.*.local

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Editor directories
.idea
.vscode
*.swp
*.swo

# OS files
.DS_Store
Thumbs.db

# Database
*.sqlite
*.sqlite3

# Test coverage
coverage
50 changes: 50 additions & 0 deletions auto-content-creator/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Base stage for all services
FROM node:20-alpine as base
WORKDIR /app
COPY package.json yarn.lock ./
COPY agents/package.json ./agents/
COPY backend/package.json ./backend/
COPY frontend/package.json ./frontend/
RUN yarn install --frozen-lockfile

# Agents build stage
FROM base as agents-build
COPY agents ./agents
COPY tsconfig.base.json ./
RUN yarn workspace @auto-content/agents build

# Backend build stage
FROM base as backend-build
COPY backend ./backend
COPY tsconfig.base.json ./
RUN yarn workspace @auto-content/backend build

# Frontend build stage
FROM base as frontend-build
COPY frontend ./frontend
COPY tsconfig.base.json ./
RUN yarn workspace @auto-content/frontend build

# Agents production stage
FROM node:20-alpine as agents
WORKDIR /app
COPY --from=agents-build /app/agents/dist ./dist
COPY --from=agents-build /app/agents/package.json ./
COPY --from=base /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]

# Backend production stage
FROM node:20-alpine as backend
WORKDIR /app
COPY --from=backend-build /app/backend/dist ./dist
COPY --from=backend-build /app/backend/package.json ./
COPY --from=base /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]

# Frontend production stage
FROM node:20-alpine as frontend
WORKDIR /app
COPY --from=frontend-build /app/frontend/dist ./dist
COPY --from=frontend-build /app/frontend/package.json ./
COPY --from=base /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]
14 changes: 8 additions & 6 deletions auto-content-creator/agents/package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
{
"name": "auto-content-creator",
"name": "@auto-content/agents",
"version": "1.0.0",
"description": "Auto Content Creator using LangGraph.js",
"main": "src/index.ts",
"private": true,
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"start": "ts-node src/index.ts",
"dev": "nodemon"
"build": "tsc",
"dev": "nodemon",
"start": "node dist/index.js"
},
"dependencies": {
"@langchain/anthropic": "^0.3.2",
Expand All @@ -27,4 +29,4 @@
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
}
}
}
29 changes: 29 additions & 0 deletions auto-content-creator/agents/src/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import dotenv from 'dotenv';

dotenv.config();

export const config = {
port: process.env.AGENTS_PORT || 3000,
openaiApiKey: process.env.OPENAI_API_KEY,
serpapiApiKey: process.env.SERPAPI_API_KEY,
model: 'gpt-4o-mini',
environment: process.env.NODE_ENV || 'development',
llmConfig: {
generation: {
temperature: 0.7,
maxTokens: 2000
},
reflection: {
temperature: 0.2,
maxTokens: 1000
},
research: {
temperature: 0.2,
maxTokens: 1000
},
feedback: {
temperature: 0.4,
maxTokens: 1500
}
}
};
96 changes: 15 additions & 81 deletions auto-content-creator/agents/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,100 +1,34 @@
import express, { Request, Response, NextFunction } from 'express';
import { writerAgent } from './writerAgent';
import dotenv from 'dotenv';

dotenv.config();
import { writerRouter } from './routes/writer';
import logger from './logger';
import { config } from './config';

// Create an Express application
const app = express();

// Add JSON parsing middleware
app.use(express.json());

// Specify the port number for the server
const port: number = process.env.AGENTS_PORT ? parseInt(process.env.AGENTS_PORT) : 3000;

// Add this new endpoint for feedback
app.post('/writer/:threadId/feedback', (req: Request, res: Response, next: NextFunction) => {
console.log('Received feedback request:', req.body);
(async () => {
try {
const { feedback } = req.body;
const threadId = req.params.threadId;
const port = config.port;

if (!feedback) {
return res.status(400).json({ error: 'Feedback is required' });
}

console.log('Processing feedback for thread:', threadId);

const result = await writerAgent.continueDraft({
threadId,
feedback,
});

// Only return the latest content
res.json({
threadId,
content: result.finalContent
});
} catch (error) {
console.error('Error in feedback endpoint:', error);
next(error);
}
})();
});

// Modify the original /writer endpoint to return threadId
app.post('/writer', (req: Request, res: Response, next: NextFunction) => {
console.log('Received request body:', req.body);
(async () => {
try {
const { category, topic, contentType, otherInstructions } = req.body;

if (!category || !topic || !contentType) {
console.log('Category, topic, and contentType are required');
return res.status(400).json({ error: 'Category, topic, and contentType are required' });
}
app.use(express.json());

const result = await writerAgent.startDraft({
category,
topic,
contentType,
otherInstructions,
});
// Routes
app.use('/writer', writerRouter);

res.json({
threadId: result.threadId,
finalContent: result.finalContent,
research: result.research,
reflections: result.reflections,
drafts: result.drafts,
feedbackHistory: result.feedbackHistory,
});
} catch (error) {
console.error('Error in /writer endpoint:', error);
next(error);
}
})();
// Health check route
app.get('/', (req, res) => {
logger.info('Health check request received');
res.send('Auto Content Creator Agents Service is running!');
});

// Error handling middleware
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
console.error(err.stack);
logger.error('Unhandled error:', err);
res.status(500).json({
error: 'An error occurred while processing your request',
details: err.message,
details: err.message
});
});

// Add a simple route for testing
app.get('/', (req, res) => {
console.log('Received request on root route');
res.send('Auto Content Creator Backend is running!');
});

// Start the server and listen on the specified port
// Start server
app.listen(port, () => {
// Log a message when the server is successfully running
console.log(`Server is running on http://localhost:${port}`);
logger.info(`Agents service is running on http://localhost:${port}`);
});
5 changes: 3 additions & 2 deletions auto-content-creator/agents/src/logger.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import winston from 'winston';
import { config } from './config';

const logger = winston.createLogger({
level: 'info',
Expand All @@ -8,14 +9,14 @@ const logger = winston.createLogger({
winston.format.splat(),
winston.format.json()
),
defaultMeta: { service: 'writer-agent' },
defaultMeta: { service: 'writer-agent', environment: config.environment },
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' }),
],
});

if (process.env.NODE_ENV !== 'production') {
if (config.environment !== 'production') {
logger.add(
new winston.transports.Console({
format: winston.format.combine(winston.format.colorize(), winston.format.simple()),
Expand Down
68 changes: 68 additions & 0 deletions auto-content-creator/agents/src/routes/writer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import express from 'express';
import { writerAgent } from '../services/writerAgent';
import logger from '../logger';

const router = express.Router();

router.post('/', (req, res, next) => {
logger.info('Received request to start new draft:', req.body);
(async () => {
try {
const { category, topic, contentType, otherInstructions } = req.body;

if (!category || !topic || !contentType) {
logger.warn('Missing required fields');
return res.status(400).json({ error: 'Category, topic, and contentType are required' });
}

const result = await writerAgent.startDraft({
category,
topic,
contentType,
otherInstructions,
});

res.json({
threadId: result.threadId,
finalContent: result.finalContent,
research: result.research,
reflections: result.reflections,
drafts: result.drafts,
feedbackHistory: result.feedbackHistory,
});
} catch (error) {
logger.error('Error in writer endpoint:', error);
next(error);
}
})();
});

router.post('/:threadId/feedback', (req, res, next) => {
logger.info('Received feedback request:', req.body);
(async () => {
try {
const { feedback } = req.body;
const threadId = req.params.threadId;

if (!feedback) {
return res.status(400).json({ error: 'Feedback is required' });
}

logger.info('Processing feedback for thread:', threadId);

const result = await writerAgent.continueDraft({
threadId,
feedback,
});

res.json({
content: result.finalContent
});
} catch (error) {
logger.error('Error in feedback endpoint:', error);
next(error);
}
})();
});

export const writerRouter = router;
Loading

0 comments on commit d278d13

Please sign in to comment.