Skip to content

Commit

Permalink
feat: improve model fetching logic and enhance error handling in Open…
Browse files Browse the repository at this point in the history
…AI model provider
  • Loading branch information
Sma1lboy committed Jan 16, 2025
1 parent b1e9be7 commit 7352ba4
Show file tree
Hide file tree
Showing 11 changed files with 285 additions and 313 deletions.
28 changes: 28 additions & 0 deletions .tmuxinator/dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: codefox
root: <%= ENV["PWD"] %>

on_project_start: tmux set-option -g prefix C-a

windows:
- backend:
root: <%= ENV["PWD"] %>/backend
panes:
- backend:
- echo "Backend Server (Ctrl+a 1 to focus, Ctrl+a r to restart)"
- pnpm dev
- frontend:
root: <%= ENV["PWD"] %>/frontend
layout: main-vertical
panes:
- frontend:
- echo "Frontend Server (Ctrl+a 2 to focus, Ctrl+a r to restart)"
- pnpm dev
- codegen:
- echo "Codegen Watch (Ctrl+a 2 to focus, Ctrl+a r to restart)"
- pnpm generate:watch
- llm:
root: <%= ENV["PWD"] %>/llm-server
panes:
- llm:
- echo "LLM Server (Ctrl+a 3 to focus, Ctrl+a r to restart)"
- pnpm dev
122 changes: 122 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,125 @@ graph TD
classDef layerStyle fill:#f4f4f4,stroke:#666,stroke-width:1px,stroke-dasharray: 5 5
class Project_Generate_Layer layerStyle
```

# CodeFox Development Guide

## Prerequisites

Before you begin, ensure you have the following installed:

- Node.js >= 18.0.0
- PNPM 9.1.2 (`npm install -g [email protected]`)
- Tmux >= 3.2
- Tmuxinator >= 3.0.0 (`gem install tmuxinator`)

## Project Structure

The project consists of three main components:

```
codefox/
├── backend/ # NestJS backend server
├── frontend/ # Next.js frontend application
└── llm-server/ # LLM service
```

## Installation

1. Clone the repository:

```bash
git clone <repository-url>
cd codefox
```

2. Install dependencies:

```bash
pnpm install
```

3. Set up environment variables:

```bash
# Copy and configure environment files for each service
cp backend/.env.template backend/.env
cp frontend/.env.template frontend/.env
cp llm-server/.env.template llm-server/.env
```

## Development

### Using Tmuxinator (Recommended)

The project includes a Tmuxinator configuration for easy development. This will start all services in separate windows with proper layouts:

```bash
pnpm dev:tmux
```

This command will create:

- Window 1: Backend server
- Window 2: Frontend development server (left) and GraphQL codegen watcher (right)
- Window 3: LLM server

Tmux Navigation:

- `Ctrl+a 1/2/3` - Switch between windows
- `Ctrl+a r` - Restart current pane's service
- `Ctrl+a d` - Detach from session

### Manual Development

If you prefer to run services individually:

```bash
# Start all services
pnpm dev

# Or start services individually
pnpm dev:backend # Start backend only
cd frontend && pnpm dev # Start frontend only
cd llm-server && pnpm dev # Start LLM server only
```

## Additional Commands

```bash
pnpm build # Build all packages
pnpm lint # Run linting
pnpm format # Format code
pnpm test # Run tests
```

## GraphQL Code Generation

The frontend uses GraphQL with automatic type generation. The codegen watcher is automatically started in the Tmuxinator setup, but you can also run it manually:

```bash
cd frontend
pnpm generate:watch
```

## Troubleshooting

If you encounter any issues:

1. Ensure all environment variables are properly set
2. Check if all required services are running
3. Clear node_modules and reinstall dependencies:

```bash
pnpm clean
pnpm install
```

4. For Tmuxinator issues:
- Ensure Tmux is running version 3.2 or higher
- Check if the session is already running: `tmux ls`
- Kill existing session if needed: `tmux kill-session -t codefox`

## License

ISC
Binary file modified backend/database.db
Binary file not shown.
2 changes: 1 addition & 1 deletion backend/src/chat/chat.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export class ChatResolver {
): Promise<string[]> {
try {
const response = await this.chatProxyService.fetchModelTags();
return response.models.data.map((model) => model.id); // Adjust based on model structure
return response;
} catch (error) {
throw new Error('Failed to fetch model tags');
}
Expand Down
4 changes: 2 additions & 2 deletions backend/src/chat/chat.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ export class ChatProxyService {
);
}

async fetchModelTags(): Promise<any> {
return this.models.fetchModelsName();
async fetchModelTags(): Promise<string[]> {
return await this.models.fetchModelsName();
}
}

Expand Down
31 changes: 25 additions & 6 deletions backend/src/common/model-provider/openai-model-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export class OpenAIModelProvider implements IModelProvider {
model: string,
): CustomAsyncIterableIterator<ChatCompletionChunk> {
let stream: Stream<OpenAIChatCompletionChunk> | null = null;
let streamIterator: AsyncIterator<OpenAIChatCompletionChunk> | null = null;
const modelName = model || input.model;
const queue = this.getQueueForModel(modelName);

Expand All @@ -128,30 +129,35 @@ export class OpenAIModelProvider implements IModelProvider {

if (!result) throw new Error('Queue operation failed');
stream = result;
// 创建一个新的迭代器并保存它
streamIterator = stream[Symbol.asyncIterator]();
}
return stream;
return streamIterator;
};

const iterator: CustomAsyncIterableIterator<ChatCompletionChunk> = {
async next() {
try {
const currentStream = await createStream();
const chunk = await currentStream[Symbol.asyncIterator]().next();
const currentIterator = await createStream();
const chunk = await currentIterator.next();
return {
done: chunk.done,
value: chunk.value as ChatCompletionChunk,
};
} catch (error) {
stream = null;
streamIterator = null;
throw error;
}
},
async return() {
stream = null;
streamIterator = null;
return { done: true, value: undefined };
},
async throw(error) {
stream = null;
streamIterator = null;
throw error;
},
[Symbol.asyncIterator]() {
Expand All @@ -164,11 +170,24 @@ export class OpenAIModelProvider implements IModelProvider {

async fetchModelsName(): Promise<string[]> {
try {
const models = await this.openai.models.list();
return models.data.map((model) => model.id);
const response = await this.openai.models.list();
this.logger.debug('Raw models response:', JSON.stringify(response));

const responseBody = JSON.parse((response as any).body);
this.logger.debug('Parsed models response:', responseBody);

if (responseBody?.models?.data) {
this.logger.debug('Extracted model names:', responseBody.models.data);
const res = responseBody.models.data.map((res) => res.id);
this.logger.debug('Returning model names:', res);
return res;
}

this.logger.warn('Unexpected models response format:', responseBody);
return [];
} catch (error) {
this.logger.error('Error fetching models:', error);
throw error;
return [];
}
}

Expand Down
14 changes: 14 additions & 0 deletions frontend/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
schema: './src/graphql/schema.gql',
documents: ['src/**/*.tsx', 'src/**/*.ts'],
ignoreNoDocuments: true,
generates: {
'src/graphql/type.tsx': {
plugins: [
Expand All @@ -28,6 +30,18 @@ const config: CodegenConfig = {
},
},
},
hooks: {
afterOneFileWrite: ['prettier --write'],
afterAllFileWrite: ['echo "✨ GraphQL types generated successfully"'],
onWatchTriggered: (event, path) => {
console.log(`🔄 Changes detected in ${path}`);
},
onError: (error) => {
console.error('❌ GraphQL Codegen Error:', error);
return null; // Continue generation even if there are errors
},
},
watch: ['src/**/*.{ts,tsx,graphql,gql}'],
};

export default config;
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"dev": "next dev",
"start:dev": "next dev",
"start:dev-watch": "tmuxinator start -p .tmuxinator/build.yml",
"dev:watch": "tmuxinator start -p .tmuxinator/dev.yml",
"build": "next build",
"start": "next start",
"lint": "next lint --fix",
Expand Down Expand Up @@ -87,4 +88,4 @@
"ts-node": "^10.9.2",
"typescript": "^5.6.2"
}
}
}
Loading

0 comments on commit 7352ba4

Please sign in to comment.