Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: fetch_error: fetch failed #1

Closed
shanbady opened this issue Oct 18, 2023 · 21 comments
Closed

Error: fetch_error: fetch failed #1

shanbady opened this issue Oct 18, 2023 · 21 comments

Comments

@shanbady
Copy link

Getting:

Error: fetch_error: fetch failed
    at generate (file:///usr/local/lib/node_modules/codespin/dist/commands/generate.js:118:19)
    at async Object.handler (file:///usr/local/lib/node_modules/codespin/dist/index.js:117:9)

when using:
codespin gen --prompt '<some promt>'

my openai key is valid and set. any ideas?

@jeswin
Copy link
Member

jeswin commented Oct 18, 2023

Hey @shanbady,

Can you let me know which version of codespin you're using?

You can get this with codespin version.

@shanbady
Copy link
Author

latest i think. I installed via npm install -g codespin

@shanbady
Copy link
Author

codespin --version says 0.0.62

@jeswin
Copy link
Member

jeswin commented Oct 18, 2023

Can you post please:

  • the full command (including the prompt)
  • Have you done codespin init? This is not required, but just trying to understand your environment.

Also, I can send you Google Meet link to do some debugging. :)

@jeswin
Copy link
Member

jeswin commented Oct 18, 2023

Can you check if api.openai.com is accessible from your computer?

@shanbady
Copy link
Author

It is - when i hit it it responds with { "error": { "message": "Invalid URL (GET /)", "type": "invalid_request_error", "param": null, "code": null } }

@jeswin
Copy link
Member

jeswin commented Oct 18, 2023

Please share:

  • the full command (including the prompt)
  • Have you done codespin init? This is not required, but just trying to understand your environment.

I am not able to reproduce at my end; so we'll need to dig deeper.

@shanbady
Copy link
Author

I tried again with the vpn off. still getting the same.

@jeswin
Copy link
Member

jeswin commented Oct 18, 2023

I just tried:
codespin gen --prompt 'Create a typescript function that adds two numbers'

And received:

FILE: addNumbers.ts
-------------------
function addNumbers(a: number, b: number): number {
  return a + b;
}

@jeswin
Copy link
Member

jeswin commented Oct 18, 2023

Where are you located?

@shanbady
Copy link
Author

i've done a codespin init (have also tried without.

full prompt:

codespin gen --prompt 'Create a django app for email marketing to customers. This app should be multi-tenant and support multiple organizations. A user should be able to sign up for an an account, create an organization and then create a workspace. They should then be able to import customers either through csv or using the api. The app should have an "events" api where a customer could send arbitrary json formatted events associated with a customer id in the database (it should add a new customer if one does not exist). There should be an interface for viewing all event data, a view for viewing all contacts and their data. The user should also have the ability to create "segments" based on customer attribute conditions(for example, a segment could be "all contacts who have an '@gmail' email address, who have a 'birth-date' after 1999 and have a first_name attribute of 'Fred'). The main application database should be postgres. Stream processing and contact segmentation should be done using ksqlb or a no-sql database such as mongodb. Nginx should be used as the server/load balancer. The entire application should be dockerized using docker-compose.' --write

@shanbady
Copy link
Author

node -v is v19.6.0

npm -v is 9.6.7

@jeswin
Copy link
Member

jeswin commented Oct 18, 2023

Thank you.

I have a suspicion it's not able to hit the API. There are similar issues reported here: transitive-bullshit/agentic#419

That's specific to China. If you're in Boston (guessing from your profile), that wouldn't be the reason. Unless you're on a VPN, or tor etc.

@jeswin
Copy link
Member

jeswin commented Oct 18, 2023

Let me see if fetch exists in 19.6. I should have thought of that.

Add:
Tested. Exists.

@jeswin
Copy link
Member

jeswin commented Oct 18, 2023

Ah wait. There's a better way to do this.

Can you append the --debug flag to the command please?

@jeswin
Copy link
Member

jeswin commented Oct 18, 2023

You can use the following command:
codespin gen --prompt 'Create a typescript function that adds two numbers'

Once we figure it out with the prompt above, we can move to the larger prompt.

@shanbady
Copy link
Author

--- PROMPT ---
Create a typescript function that adds two numbers

-----

Respond with just the code (but exclude invocation examples etc) in the following format:

$START_FILE_CONTENTS:./some/path/filename.ext$
import a from "./a";
function somethingSomething() {
  //....
}
$END_FILE_CONTENTS:./some/path/filename.ext$


OPENAI: model=gpt-3.5-turbo
OPENAI: maxTokens=3693
---OPENAI RESPONSE---
{"data":{"id":"chatcmpl-8AsA3Ta27vbLvhjcxRUbp0pwERYDD","object":"chat.completion","created":1697602167,"model":"gpt-3.5-turbo-0613","choices":[{"index":0,"message":{"role":"assistant","content":"$START_FILE_CONTENTS:addNumbers.ts$\nfunction addNumbers(a: number, b: number): number {\n  return a + b;\n}\n$END_FILE_CONTENTS:addNumbers.ts$"},"finish_reason":"stop"}],"usage":{"prompt_tokens":76,"completion_tokens":38,"total_tokens":114}}}
FILE: addNumbers.ts
-------------------
function addNumbers(a: number, b: number): number {
  return a + b;
}

@jeswin
Copy link
Member

jeswin commented Oct 18, 2023

Ah, so that worked.

I tried your prompt, and it kinda worked as well.

FILE: ./docker-compose.yml
--------------------------
version: '3'

services:
  nginx:
    image: nginx:latest
    ports:
      - 80:80
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    depends_on:
      - web

  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: python manage.py runserver 0.0.0.0:8000
    volumes:
      - .:/code
    ports:
      - 8000:8000
    depends_on:
      - db

  db:
    image: postgres:latest
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_DB=email_marketing

FILE: ./Dockerfile
------------------
FROM python:3.9

ENV PYTHONUNBUFFERED 1

WORKDIR /code

COPY requirements.txt /code/
RUN pip install -r requirements.txt

COPY . /code/

FILE: ./requirements.txt
------------------------
Django==3.2.7
psycopg2-binary==2.9.1

FILE: ./email_marketing/settings.py
-----------------------------------
import os

# ...

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('DB_NAME', 'email_marketing'),
        'USER': os.environ.get('DB_USER', 'postgres'),
        'PASSWORD': os.environ.get('DB_PASSWORD', 'postgres'),
        'HOST': os.environ.get('DB_HOST', 'db'),
        'PORT': os.environ.get('DB_PORT', '5432'),
    }
}

# ...

FILE: ./email_marketing/urls.py
-------------------------------
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('api.urls')),
]

FILE: ./api/urls.py
-------------------
from django.urls import path
from . import views

urlpatterns = [
    path('signup/', views.signup, name='signup'),
    path('organizations/', views.OrganizationListCreateView.as_view(), name='organization-list-create'),
    path('workspaces/', views.WorkspaceListCreateView.as_view(), name='workspace-list-create'),
    path('import/customers/', views.import_customers, name='import-customers'),
    path('events/', views.EventListCreateView.as_view(), name='event-list-create'),
    path('contacts/', views.ContactListCreateView.as_view(), name='contact-list-create'),
    path('segments/', views.SegmentListCreateView.as_view(), name='segment-list-create'),
]

FILE: ./api/views.py
--------------------
from django.contrib.auth.models import User
from django.shortcuts import render
from rest_framework import generics, status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Organization, Workspace, Customer, Event, Contact, Segment
from .serializers import (
    UserSerializer, OrganizationSerializer, WorkspaceSerializer,
    CustomerSerializer, EventSerializer, ContactSerializer, SegmentSerializer
)

@api_view(['POST'])
def signup(request):
    serializer = UserSerializer(data=request.data)
    if serializer.is_valid():
        user = serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class OrganizationListCreateView(generics.ListCreateAPIView):
    queryset = Organization.objects.all()
    serializer_class = OrganizationSerializer

class WorkspaceListCreateView(generics.ListCreateAPIView):
    queryset = Workspace.objects.all()
    serializer_class = WorkspaceSerializer

@api_view(['POST'])
def import_customers(request):
    # Import customers logic
    return Response(status=status.HTTP_200_OK)

class EventListCreateView(generics.ListCreateAPIView):
    queryset = Event.objects.all()
    serializer_class = EventSerializer

class ContactListCreateView(generics.ListCreateAPIView):
    queryset = Contact.objects.all()
    serializer_class = ContactSerializer

class SegmentListCreateView(generics.ListCreateAPIView):
    queryset = Segment.objects.all()
    serializer_class = SegmentSerializer

FILE: ./api/models.py
---------------------
from django.db import models

class Organization(models.Model):
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

class Workspace(models.Model):
    name = models.CharField(max_length=255)
    organization = models.ForeignKey(Organization, on_delete=models.CASCADE)

    def __str__(self):
        return self.name

class Customer(models.Model):
    # Customer fields
    workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)

    def __str__(self):
        return f"Customer {self.id}"

class Event(models.Model):
    customer = models.ForeignKey(Customer, on_delete=models.CASCADE)
    data = models.JSONField()

class Contact(models.Model):
    # Contact fields
    workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)

    def __str__(self):
        return f"Contact {self.id}"

class Segment(models.Model):
    name = models.CharField(max_length=255)
    workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)
    conditions = models.JSONField()

    def __str__(self):
        return self.name

FILE: ./api/serializers.py
--------------------------
from django.contrib.auth.models import User
from rest_framework import serializers
from .models import Organization, Workspace, Customer, Event, Contact, Segment

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['username', 'password']
        extra_kwargs = {'password': {'write_only': True}}

    def create(self, validated_data):
        user = User.objects.create_user(**validated_data)
        return user

class OrganizationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Organization
        fields = '__all__'

class WorkspaceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Workspace
        fields = '__all__'

class CustomerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Customer
        fields = '__all__'

class EventSerializer(serializers.ModelSerializer):
    class Meta:
        model = Event
        fields = '__all__'

class ContactSerializer(serializers.ModelSerializer):
    class Meta:
        model = Contact
        fields = '__all__'

class SegmentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Segment
        fields = '__all__'

FILE: ./nginx.conf
------------------
worker_processes 1;

events { worker_connections 1024; }

http {
    sendfile on;

    upstream web {
        server web:8000;
    }

    server {
        listen 80;

        location / {
            proxy_pass http://web;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

@jeswin
Copy link
Member

jeswin commented Oct 18, 2023

Some general points though:

  1. For more advanced use cases, think of a file structure for your project, and define the prompts individually for each file.
  2. You're at the limit of exceeding default token sizes. You might to change max-tokens when generating multiple files.
  3. But the default model doesn't support large context sizes. You might need to switch to "gpt-3.5-turbo-16k" or "gpt-4" (GPT4 being way more expensive), and then specify max-tokens.

@jeswin
Copy link
Member

jeswin commented Oct 19, 2023

@shanbady Can you verify, so that I can close this?

@shanbady
Copy link
Author

That seems to have been it. you can close this

@jeswin jeswin closed this as completed Oct 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants