ran pre-commit and fixed issues

This commit is contained in:
Yannic Kilcher
2022-12-13 12:38:59 +01:00
parent ceda5481b9
commit d3d657e636
43 changed files with 213 additions and 154 deletions
-2
View File
@@ -11,10 +11,8 @@ repos:
- id: check-ast
- id: check-yaml
- id: check-json
- id: pretty-format-json
- id: check-case-conflict
- id: detect-private-key
- id: detect-aws-credentials
- id: fix-encoding-pragma
- id: forbid-submodules
- id: mixed-line-ending
+1 -1
View File
@@ -1 +1 @@
3.10.8
3.10.8
+11 -3
View File
@@ -1,4 +1,5 @@
# Open-Chat-GPT
Open chat gpt is a project meant to give everyone access to a great chat based large language model.
We believe that by doing this we will create a revolution in innovation in language. In the same way that stable-diffusion helped the world make art and images in new ways we hope open chat gpt can help improve the world by improving language itself.
@@ -15,19 +16,26 @@ We live and collaborate the work in the LAION discord. Join us!
## How do I start helping out?
Check out these pages to learn more about the project.
Check out these pages to learn more about the project.
Ping Birger on discord if you want help to get started.
http://**discordapp.com/users/birger#6875**
## More information in the notion
https://roan-iguanadon-a58.notion.site/Open-Chat-Gpt-83dd217eeeb84907a155b8a9d716fa46
## Code structure
## Bot
### Pre-commit
Run `pre-commit install` to install the pre-commit hooks.
### Bot
We have a folder named bot where code related to the bot lives.
## Backend
### Backend
We have a backend folder for backend development of the api that the discord bot sends it information to.
+1 -2
View File
@@ -4,7 +4,6 @@
Please edit `alembic.ini` and specify your database uri in the parameter `sqlalchemy.url`.
## REST Server Configuration
Please either use environment variables or create a `.env` file in the backend root directory (in which this readme file is located) to specify the `DATABASE_URI`.
@@ -15,4 +14,4 @@ Example contents of a `.env` file for the backend:
DATABASE_URI="postgresql://<username>:<password>@<host>/<database_name>"
BACKEND_CORS_ORIGINS=["http://localhost", "http://localhost:4200", "http://localhost:3000", "http://localhost:8080", "https://localhost", "https://localhost:4200", "https://localhost:3000", "https://localhost:8080", "http://dev.ocgpt.laion.ai", "https://stag.ocgpt.laion.ai", "https://ocgpt.laion.ai"]
```
```
+1 -1
View File
@@ -1 +1 @@
Generic single-database configuration.
Generic single-database configuration.
+3 -6
View File
@@ -1,9 +1,8 @@
# -*- coding: utf-8 -*-
from logging.config import fileConfig
from sqlalchemy import engine_from_config
from sqlalchemy import pool
from alembic import context
from sqlalchemy import engine_from_config, pool
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
@@ -64,9 +63,7 @@ def run_migrations_online() -> None:
)
with connectable.connect() as connection:
context.configure(
connection=connection, target_metadata=target_metadata
)
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()
@@ -1,16 +1,16 @@
# -*- coding: utf-8 -*-
"""first revision
Revision ID: 23e5fea252dd
Revises:
Revises:
Create Date: 2022-12-12 12:47:28.801354
"""
from alembic import op
import sqlalchemy as sa
from alembic import op
# revision identifiers, used by Alembic.
revision = '23e5fea252dd'
revision = "23e5fea252dd"
down_revision = None
branch_labels = None
depends_on = None
@@ -23,25 +23,29 @@ def upgrade() -> None:
sa.Column("name", sa.String(200), nullable=False),
sa.Column("service_admin_email", sa.String(128), nullable=True),
sa.Column("api_key", sa.String(300), nullable=False),
sa.Column("can_append", sa.Boolean, nullable=False, server_default='true'),
sa.Column("can_write", sa.Boolean, nullable=False, server_default='false'),
sa.Column("can_delete", sa.Boolean, nullable=False, server_default='false'),
sa.Column("can_read", sa.Boolean, nullable=False, server_default='true'),
sa.Column("can_append", sa.Boolean, nullable=False, server_default="true"),
sa.Column("can_write", sa.Boolean, nullable=False, server_default="false"),
sa.Column("can_delete", sa.Boolean, nullable=False, server_default="false"),
sa.Column("can_read", sa.Boolean, nullable=False, server_default="true"),
sa.PrimaryKeyConstraint("id"),
)
op.create_index(op.f("ix_service_client_api_key"), "service_client", ["api_key"], unique=True)
op.create_table(
"labeler",
sa.Column("id", sa.Integer, sa.Identity()),
sa.Column("display_name", sa.String(96), nullable=False),
sa.Column("discord_username", sa.String(96), nullable=True),
sa.Column("created_date", sa.DateTime, nullable=False, server_default=sa.func.current_timestamp()),
sa.Column("is_enabled", sa.Boolean, nullable=False, server_default='true'),
sa.Column("notes", sa.String(10*1024), nullable=True),
sa.Column(
"created_date",
sa.DateTime,
nullable=False,
server_default=sa.func.current_timestamp(),
),
sa.Column("is_enabled", sa.Boolean, nullable=False, server_default="true"),
sa.Column("notes", sa.String(10 * 1024), nullable=True),
sa.PrimaryKeyConstraint("id"),
sa.UniqueConstraint("discord_username")
sa.UniqueConstraint("discord_username"),
)
op.create_table(
@@ -51,8 +55,16 @@ def upgrade() -> None:
sa.Column("prompt", sa.Text, nullable=False),
sa.Column("response", sa.Text, nullable=True),
sa.Column("lang", sa.String(32), nullable=True),
sa.Column("created_date", sa.DateTime(), nullable=False, server_default=sa.func.current_timestamp()),
sa.ForeignKeyConstraint(["labeler_id"], ["labeler.id"],),
sa.Column(
"created_date",
sa.DateTime(),
nullable=False,
server_default=sa.func.current_timestamp(),
),
sa.ForeignKeyConstraint(
["labeler_id"],
["labeler.id"],
),
sa.PrimaryKeyConstraint("id"),
)
op.create_index(op.f("prompt_labeler_id"), "prompt", ["labeler_id"], unique=False)
+15 -9
View File
@@ -1,10 +1,11 @@
# -*- coding: utf-8 -*-
from typing import Generator
from sqlmodel import Session
from fastapi import Security, HTTPException
from fastapi.security.api_key import APIKeyQuery, APIKeyHeader, APIKey
from app.database import engine
from app.models import ServiceClient
from fastapi import HTTPException, Security
from fastapi.security.api_key import APIKey, APIKeyHeader, APIKeyQuery
from sqlmodel import Session
from starlette.status import HTTP_403_FORBIDDEN
@@ -28,16 +29,21 @@ async def get_api_key(
def api_auth(
api_key: APIKey, db: Session, create: bool = False, read: bool = True, update: bool = False, delete: bool = False
api_key: APIKey,
db: Session,
create: bool = False,
read: bool = True,
update: bool = False,
delete: bool = False,
) -> ServiceClient:
if api_key is not None:
api_client = db.query(ServiceClient).filter(ServiceClient.api_key == api_key).first()
if api_client is not None:
if (
(create == False or api_client.can_append)
and (read == False or api_client.can_read)
and (update == False or api_client.can_write)
and (delete == False or api_client.can_delete)
(create is False or api_client.can_append)
and (read is False or api_client.can_read)
and (update is False or api_client.can_write)
and (delete is False or api_client.can_delete)
):
return api_client
+2 -2
View File
@@ -1,6 +1,6 @@
from fastapi import APIRouter
# -*- coding: utf-8 -*-
from app.api.v1 import labelers, prompts
from fastapi import APIRouter
api_router = APIRouter()
api_router.include_router(labelers.router, prefix="/labelers", tags=["labelers"])
+5 -6
View File
@@ -1,13 +1,12 @@
# -*- coding: utf-8 -*-
from typing import Any, List
from fastapi import APIRouter, Depends, HTTPException
from fastapi.security.api_key import APIKey
from sqlmodel import Session
from starlette.status import HTTP_404_NOT_FOUND, HTTP_400_BAD_REQUEST
from app import crud, schemas
from app.api import deps
from fastapi import APIRouter, Depends, HTTPException
from fastapi.security.api_key import APIKey
from sqlmodel import Session
from starlette.status import HTTP_400_BAD_REQUEST, HTTP_404_NOT_FOUND
router = APIRouter()
+6 -7
View File
@@ -1,13 +1,12 @@
# -*- coding: utf-8 -*-
from typing import Any, List
from fastapi import APIRouter, Depends, HTTPException
from fastapi.security.api_key import APIKey
from sqlmodel import Session
from starlette.status import HTTP_404_NOT_FOUND, HTTP_400_BAD_REQUEST, HTTP_401_UNAUTHORIZED
from app import crud, schemas
from app.api import deps
from fastapi import APIRouter, Depends, HTTPException
from fastapi.security.api_key import APIKey
from sqlmodel import Session
from starlette.status import HTTP_400_BAD_REQUEST, HTTP_401_UNAUTHORIZED, HTTP_404_NOT_FOUND
router = APIRouter()
@@ -50,7 +49,7 @@ def create_prompt(
raise HTTPException(status_code=HTTP_404_NOT_FOUND, detail="Invalid labeler user name")
if not labeler.is_enabled:
raise HTTPException(status_code=HTTP_401_UNAUTHORIZED, detail="Labeler disabled")
item_in.labeler_id = labeler.id
item_in.discord_username = None
item = crud.prompt.create(db=db, obj_in=item_in)
+2
View File
@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
from typing import List, Optional, Union
from pydantic import AnyHttpUrl, BaseSettings, PostgresDsn, validator
+4 -1
View File
@@ -1,2 +1,5 @@
# -*- coding: utf-8 -*-
from .crud_labeler import labeler
from .crud_prompt import prompt
from .crud_prompt import prompt
__all__ = ["labeler", "prompt"]
+3 -11
View File
@@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
from typing import Any, Dict, Generic, List, Optional, Type, TypeVar, Union
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel
from sqlmodel import Session, SQLModel
ModelType = TypeVar("ModelType", bound=SQLModel)
CreateSchemaType = TypeVar("CreateSchemaType", bound=BaseModel)
UpdateSchemaType = TypeVar("UpdateSchemaType", bound=BaseModel)
@@ -25,9 +25,7 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
def get(self, db: Session, id: Any) -> Optional[ModelType]:
return db.query(self.model).filter(self.model.id == id).first()
def get_multi(
self, db: Session, *, begin_id: int = 0, limit: int = 100
) -> List[ModelType]:
def get_multi(self, db: Session, *, begin_id: int = 0, limit: int = 100) -> List[ModelType]:
return db.query(self.model).filter(self.model.id >= begin_id).limit(limit).all()
def create(self, db: Session, *, obj_in: CreateSchemaType) -> ModelType:
@@ -38,13 +36,7 @@ class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]):
db.refresh(db_obj)
return db_obj
def update(
self,
db: Session,
*,
db_obj: ModelType,
obj_in: Union[UpdateSchemaType, Dict[str, Any]]
) -> ModelType:
def update(self, db: Session, *, db_obj: ModelType, obj_in: Union[UpdateSchemaType, Dict[str, Any]]) -> ModelType:
obj_data = jsonable_encoder(db_obj)
if isinstance(obj_in, dict):
update_data = obj_in
+1
View File
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from typing import Optional
from app.crud.base import CRUDBase
+1
View File
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from app.crud.base import CRUDBase
from app.models.prompt import Prompt
from app.schemas.prompt import PromptCreate
+2 -1
View File
@@ -1,4 +1,5 @@
from sqlmodel import create_engine
# -*- coding: utf-8 -*-
from app.config import settings
from sqlmodel import create_engine
engine = create_engine(settings.DATABASE_URI)
+11 -12
View File
@@ -1,16 +1,15 @@
import dataclasses
from datetime import datetime
import json
from typing import Optional
# -*- coding: utf-8 -*-
# flake8: noqa
import argparse
import dataclasses
import json
from dataclasses import dataclass
from sqlmodel import Session, SQLModel, create_engine
from app.config import settings
from datetime import datetime
from typing import Optional
import app.api.deps
from app.config import settings
from sqlmodel import Session, SQLModel, create_engine
def main():
@@ -24,14 +23,14 @@ def main():
app.api.deps.engine = engine
"""
with Session(engine) as session:
with Session(engine) as session:
# create a test serivice
#sc1 = ServiceClient(name='blub', api_key='1234')
#session.add(sc1)
session.commit()
"""
if __name__ == '__main__':
if __name__ == "__main__":
main()
+4 -6
View File
@@ -1,12 +1,10 @@
# -*- coding: utf-8 -*-
from app.api.v1.api import api_router
from app.config import settings
from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware
from app.api.v1.api import api_router
from app.config import settings
app = FastAPI(
title=settings.PROJECT_NAME, openapi_url=f"{settings.API_V1_STR}/openapi.json"
)
app = FastAPI(title=settings.PROJECT_NAME, openapi_url=f"{settings.API_V1_STR}/openapi.json")
# Set all CORS enabled origins
if settings.BACKEND_CORS_ORIGINS:
+4 -1
View File
@@ -1,3 +1,6 @@
from .service_client import ServiceClient
# -*- coding: utf-8 -*-
from .labeler import Labeler
from .prompt import Prompt
from .service_client import ServiceClient
__all__ = ["Labeler", "Prompt", "ServiceClient"]
+7 -2
View File
@@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
from datetime import datetime
from typing import Optional
import sqlalchemy as sa
from sqlmodel import Field, SQLModel
from typing import Optional
class Labeler(SQLModel, table=True):
@@ -9,6 +11,9 @@ class Labeler(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
display_name: str
discord_username: str
created_date: Optional[datetime] = Field(sa_column=sa.Column(sa.DateTime(), nullable=False, server_default=sa.func.current_timestamp()), nullable=False)
created_date: Optional[datetime] = Field(
sa_column=sa.Column(sa.DateTime(), nullable=False, server_default=sa.func.current_timestamp()),
nullable=False,
)
is_enabled: bool
notes: str
+7 -3
View File
@@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
from datetime import datetime
from typing import Optional
import sqlalchemy as sa
from sqlmodel import Field, SQLModel
from typing import Optional
class Prompt(SQLModel, table=True):
@@ -11,5 +13,7 @@ class Prompt(SQLModel, table=True):
prompt: str
response: Optional[str]
lang: Optional[str]
created_date: Optional[datetime] = Field(sa_column=sa.Column(sa.DateTime(), nullable=False, server_default=sa.func.current_timestamp()), nullable=False)
created_date: Optional[datetime] = Field(
sa_column=sa.Column(sa.DateTime(), nullable=False, server_default=sa.func.current_timestamp()),
nullable=False,
)
+3 -1
View File
@@ -1,6 +1,8 @@
from sqlmodel import Field, SQLModel
# -*- coding: utf-8 -*-
from typing import Optional
from sqlmodel import Field, SQLModel
class ServiceClient(SQLModel, table=True):
__tablename__ = "service_client"
+3
View File
@@ -1,2 +1,5 @@
# -*- coding: utf-8 -*-
from .labeler import Labeler, LabelerCreate, LabelerUpdate
from .prompt import Prompt, PromptCreate
__all__ = ["Labeler", "LabelerCreate", "LabelerUpdate", "Prompt", "PromptCreate"]
+3 -1
View File
@@ -1,5 +1,7 @@
from typing import Optional
# -*- coding: utf-8 -*-
from datetime import datetime
from typing import Optional
from pydantic import BaseModel
+3 -1
View File
@@ -1,5 +1,7 @@
from typing import Optional
# -*- coding: utf-8 -*-
from datetime import datetime
from typing import Optional
from pydantic import BaseModel
+3 -3
View File
@@ -1,9 +1,9 @@
alembic==1.8.1
fastapi==0.88.0
psycopg2-binary==2.9.5
pydantic==1.9.1
python-dotenv==0.21.0
SQLAlchemy==1.4.41
sqlmodel==0.0.8
starlette==0.22.0
uvicorn==0.20.0
psycopg2-binary==2.9.5
alembic==1.8.1
python-dotenv==0.21.0
+1 -1
View File
@@ -1,3 +1,3 @@
#!/usr/bin/env bash
uvicorn app.main:app --reload
uvicorn app.main:app --reload
+3
View File
@@ -1,11 +1,14 @@
# open-chat-gpt
This is the github repo for the open-chat-gpt project.
We are currently building a discord bot in order to make everyone contribute with great prompts and answers.
Join us!
https://discord.gg/ZUfPw6jP
## Project description
We are calling the community for help to collect ChatGPT-like Instruction-Fulfillment datasamples via Discord. People can post Instructions they think would make sense for ChatGPT-like systems & also provide a good reference answer for it.
## Todo
Figure out ouath flow for the app to work inside the open-chat-gpt testing channel here. https://discord.gg/JJSKtRhv
+14 -15
View File
@@ -1,13 +1,15 @@
bot_url = "https://discord.com/api/oauth2/authorize?client_id=1051614245940375683&permissions=8&scope=bot"
# -*- coding: utf-8 -*-
import discord
import json
import os
import requests
import discord
import requests
from discord import app_commands
from dotenv import load_dotenv
bot_url = "https://discord.com/api/oauth2/authorize?client_id=1051614245940375683&permissions=8&scope=bot"
# Load up all the important environment variables.
load_dotenv()
@@ -25,6 +27,7 @@ headers = {"X-API-Key": API_SERVER_KEY}
# For testing only.
TEST_GUILD = os.getenv("TEST_GUILD")
# Initiate the client and command tree to create slash commands.
class OpenChatGPTClient(discord.Client):
def __init__(self, *, intents: discord.Intents):
@@ -40,7 +43,7 @@ class OpenChatGPTClient(discord.Client):
await self.tree.sync(guild=guild)
else:
# This can take up to an hour for the commands to be registered.
await tree.sync()
await self.tree.sync()
print("Ready!")
@@ -63,7 +66,7 @@ async def register(interaction: discord.Interaction):
await interaction.response.send_message(f"Added you {interaction.user.name}")
else:
print(response)
await interaction.response.send_message(f"Failed to add you")
await interaction.response.send_message("Failed to add you")
@client.tree.command()
@@ -74,13 +77,11 @@ async def list_participants(interaction: discord.Interaction):
names = ",".join([labeler["display_name"] for labeler in response.json()])
await interaction.response.send_message(f"Found these users: {names}")
else:
await interaction.response.send_message(f"Failed to fetch participants")
await interaction.response.send_message("Failed to fetch participants")
@client.tree.command()
async def add_prompt(
interaction: discord.Interaction, prompt: str, response: str, language: str = "en"
):
async def add_prompt(interaction: discord.Interaction, prompt: str, response: str, language: str = "en"):
"""Uploads a single prompt to the server."""
prompt = {
"discord_username": f"{interaction.user.id}",
@@ -91,15 +92,13 @@ async def add_prompt(
}
response = requests.post(prompts_url, headers=headers, json=prompt)
if response.status_code == 200:
await interaction.response.send_message(f"Added your prompt")
await interaction.response.send_message("Added your prompt")
else:
await interaction.response.send_message(f"Failed to add the prompt")
await interaction.response.send_message("Failed to add the prompt")
@client.tree.command()
async def add_prompts_set(
interaction: discord.Interaction, prompts: discord.Attachment
):
async def add_prompts_set(interaction: discord.Interaction, prompts: discord.Attachment):
"""Uploads a batch of prompts to the server."""
# Loading a bunch of prompts from a file can take a while. So first defer
# the response to ensure we're able to later tell the user what happened.
@@ -122,7 +121,7 @@ async def add_prompts_set(
}
response = requests.post(prompts_url, headers=headers, json=prompt)
if response.status_code != 200:
await interaction.followup.send(f"Failed to upload")
await interaction.followup.send("Failed to upload")
return
count += 1
await interaction.followup.send(f"Loaded up {count} prompts")
+3 -8
View File
@@ -1,6 +1,5 @@
from setuptools import setup, find_packages
from pathlib import Path
import os
# -*- coding: utf-8 -*-
from setuptools import find_packages, setup
if __name__ == "__main__":
import os
@@ -8,11 +7,7 @@ if __name__ == "__main__":
def _read_reqs(relpath):
fullpath = os.path.join(os.path.dirname(__file__), relpath)
with open(fullpath) as f:
return [
s.strip()
for s in f.readlines()
if (s.strip() and not s.startswith("#"))
]
return [s.strip() for s in f.readlines() if (s.strip() and not s.startswith("#"))]
REQUIREMENTS = _read_reqs("requirements.txt")
+13
View File
@@ -0,0 +1,13 @@
[tool.isort]
profile = "black"
filter_files = true
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true
ensure_newline_before_comments = true
line_length = 120
[tool.black]
line-length = 120
target-version = ['py310']
+3
View File
@@ -0,0 +1,3 @@
[flake8]
max-line-length = 120
extend-ignore = E203, W503, E501, E741
+2 -2
View File
@@ -13,8 +13,8 @@
"web-vitals": "^2.1.4"
},
"scripts": {
"predeploy" : "npm run build",
"deploy" : "gh-pages -d build",
"predeploy": "npm run build",
"deploy": "gh-pages -d build",
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
+1 -4
View File
@@ -5,10 +5,7 @@
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Open-Chat-GPT"
/>
<meta name="description" content="Open-Chat-GPT" />
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
+8 -4
View File
@@ -14,10 +14,14 @@
}
.App-header {
background: linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),
linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),
linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%);
background: black;
background: linear-gradient(
217deg,
rgba(255, 0, 0, 0.8),
rgba(255, 0, 0, 0) 70.71%
),
linear-gradient(127deg, rgba(0, 255, 0, 0.8), rgba(0, 255, 0, 0) 70.71%),
linear-gradient(336deg, rgba(0, 0, 255, 0.8), rgba(0, 0, 255, 0) 70.71%);
background: black;
min-height: 100vh;
display: flex;
flex-direction: column;
+16 -7
View File
@@ -1,5 +1,5 @@
import logo from './logo.svg';
import './App.css';
import logo from "./logo.svg";
import "./App.css";
function App() {
return (
@@ -8,14 +8,23 @@ function App() {
{/* <img src={logo} className="App-logo" alt="logo" /> */}
<h2>Open Chat Gpt</h2>
<p>
Open chat gpt is a project meant to give everyone access to a great chat based large language model.</p>
<p>
We believe that by doing this we will create a revolution in innovation in language. In the same way that stable-diffusion helped the world make art and images in new ways we hope open chat gpt can help improve the world by improving language itself.
Open chat gpt is a project meant to give everyone access to a great
chat based large language model.
</p>
<p>
We believe that by doing this we will create a revolution in
innovation in language. In the same way that stable-diffusion helped
the world make art and images in new ways we hope open chat gpt can
help improve the world by improving language itself.
</p>
<h2>How can you help?</h2>
<p>All open source projects begins with people like you. Open source is the belief that if we collaborate we can together gift our knowledge and technology to the world for the benefit of humanity.</p>
<p>
All open source projects begins with people like you. Open source is
the belief that if we collaborate we can together gift our knowledge
and technology to the world for the benefit of humanity.
</p>
<h2>I'm in! Now what?</h2>
<p>We live and collaborate the work in the LAION discord. Join us!</p>
<a
+3 -3
View File
@@ -1,7 +1,7 @@
import { render, screen } from '@testing-library/react';
import App from './App';
import { render, screen } from "@testing-library/react";
import App from "./App";
test('renders learn react link', () => {
test("renders learn react link", () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
+3 -3
View File
@@ -1,13 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace;
}
+6 -6
View File
@@ -1,10 +1,10 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
const root = ReactDOM.createRoot(document.getElementById('root'));
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
+1 -1
View File
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

+2 -2
View File
@@ -1,6 +1,6 @@
const reportWebVitals = onPerfEntry => {
const reportWebVitals = (onPerfEntry) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
+1 -1
View File
@@ -2,4 +2,4 @@
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';
import "@testing-library/jest-dom";