반응형

ChatGPT 의 API 를 연결하려면 우선 로그인을 해야한다. 로그인을 하고 나서 Documentation 탭에 들어간다. API Reference 항목에서 Authentication 항목을 클릭하면 글 내용 중 볼드 처리된 API Keys 가 보이는데 이를 클릭하면 API Key 를 생성할 수 있다.

 

 

키가 발급되고 나면 팝업창이 뜨는데 전체 키를 보여주며 닫으면 다시 볼 수 없으니 복사를 잘 해놓자.

이제 적당한 폴더를 만들어

npm install openai

를 입력해 패키지를 설치하자.

 

 

https://platform.openai.com/docs/api-reference/chat/create

openAI 홈페이지에 가면 아주 잘 나와있으니 참고하면 편하다.

api.js 파일을 만들어 다음과 같이 입력한다.

const { Configuration, OpenAIApi } = require("openai");

const configuration = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
});
const openai = new OpenAIApi(configuration);

const completion = await openai.createChatCompletion({
  model: "gpt-3.5-turbo",
  messages: [{role: "user", content: "Hello world"}],
});
console.log(completion.data.choices[0].message);

위의 코드를 실행하면 다음과 같은 response를 받을 수 있다.

{
  "id": "chatcmpl-123",
  "object": "chat.completion",
  "created": 1677652288,
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "\\n\\nHello there, how may I assist you today?",
    },
    "finish_reason": "stop"
  }],
  "usage": {
    "prompt_tokens": 9,
    "completion_tokens": 12,
    "total_tokens": 21
  }
}

Request Body 를 더 자세피 살펴보면

  • model(Required) : api 에 사용되는 모델
  • message(Required) : 전송할 메시지
  • temperature : 0~2 값을 입력. 더 높은 값일 수록 랜덤한 대답이 생성
  • top_p : temperature를 대체할 변수. 따라서 동시에 사용하지말자.
  • n : 각 입력 메시지에 대해 생성할 대화 완료 선택사항 수. 기본값은 1
  • stream : 생성되는 대답의 부분이 출력. 대답이 끊어서 전달된다.
response = openai.ChatCompletion.create(
    model='gpt-3.5-turbo',
    messages=[
        {'role': 'user', 'content': 'Count to 100, with a comma between each number and no newlines. E.g., 1, 2, 3, ...'}
    ],
    temperature=0,
    stream=True  # again, we set stream=True
)

위의 request 를 보내고

for chunk in response:
    chunk_time = time.time() - start_time  # calculate the time delay of the chunk
    collected_chunks.append(chunk)  # save the event response
    chunk_message = chunk['choices'][0]['delta']  # extract the message
    collected_messages.append(chunk_message)  # save the message
    print(f"Message received {chunk_time:.2f} seconds after request: {chunk_message}")

다음과 같이 response 를 확인한다면

Message received 0.10 seconds after request: {
  "role": "assistant"
}
Message received 0.10 seconds after request: {
  "content": "\\n\\n"
}
Message received 0.10 seconds after request: {
  "content": "1"
}
Message received 0.11 seconds after request: {
  "content": ","
}
Message received 0.12 seconds after request: {
  "content": " "
}
Message received 0.13 seconds after request: {
  "content": "2"
}
...
Message received 0.13 seconds after request: {
  "content": "100"
}

과 같은 출력을 할 수 있다.

  • stop : API가 추가 토큰 생성을 중지하는 최대 4개의 시퀀스.
  • max_tokens : 한번의 대답이 생성되기 위한 최대 토큰의 개수
  • presense_penalty : -2~2 사이의 숫자이며, 양수로 갈 수록 새로운 토큰이 지금까지 텍스트에 나타나는지 여부에 따라 대답을 다르게 한다.
  • frequency_penalty : -2~2 사이의 숫자이며, 양수로 갈수록 빈도를 기준으로 새로운 토큰에 페널티를 줘 동일한 행 생성을 막는다.
  • logit_bias : -100~100 사이의 값에 매핑한 json 개체를 이용해 지정된 값에 따른 토큰이 나타날 가능서을 수정한다.
  • user : user 를 입력해 openai 에서 로그를 수집해 피드백을 줄 수 있게 허가해준다.npm install openaiapi.js 파일을 만들어 다음과 같이 입력한다.위의 코드를 실행하면 다음과 같은 response를 받을 수 있다.Request Body 를 더 자세피 살펴보면
    • model : api 에 사용되는 모델
    • message : 전송할 메시지
    • temperature : 0~2 값을 입력. 더 높은 값일 수록 랜덤한 대답이 생성
    • top_p : temperature를 대체할 변수. 따라서 동시에 사용하지말자.
    • n : 각 입력 메시지에 대해 생성할 대화 완료 선택사항 수. 기본값은 1
    • stream : 생성되는 대답의 부분이 출력. 대답이 끊어서 전달된다.
    response = openai.ChatCompletion.create(
        model='gpt-3.5-turbo',
        messages=[
            {'role': 'user', 'content': 'Count to 100, with a comma between each number and no newlines. E.g., 1, 2, 3, ...'}
        ],
        temperature=0,
        stream=True  # again, we set stream=True
    )
    
    위의 request 를 보내고다음과 같이 response 를 확인한다면과 같은 출력을 할 수 있다.
    • stop : API가 추가 토큰 생성을 중지하는 최대 4개의 시퀀스.
    • max_tokens : 한번의 대답이 생성되기 위한 최대 토큰의 개수
    • presense_penalty : -2~2 사이의 숫자이며, 양수로 갈 수록 새로운 토큰이 지금까지 텍스트에 나타나는지 여부에 따라 대답을 다르게 한다.
    • frequency_penalty : -2~2 사이의 숫자이며, 양수로 갈수록 빈도를 기준으로 새로운 토큰에 페널티를 줘 동일한 행 생성을 막는다.
    • logit_bias : -100~100 사이의 값에 매핑한 json 개체를 이용해 지정된 값에 따른 토큰이 나타날 가능서을 수정한다.
    • user : user 를 입력해 openai 에서 로그를 수집해 피드백을 줄 수 있게 허가해준다.
  • Message received 0.10 seconds after request: { "role": "assistant" }
  • Message received 0.10 seconds after request: { "content": "\\n\\n" }
  • Message received 0.10 seconds after request: { "content": "1" }
  • Message received 0.11 seconds after request: { "content": "," }
  • Message received 0.12 seconds after request: { "content": " " }
  • Message received 0.13 seconds after request: { "content": "2" }
  • ...
  • Message received 0.13 seconds after request: { "content": "100" }
반응형
반응형

MSI 윈도우 설치 시 드라이버를 모르고 삭제했을 경우 MSI 공식 홈페이지에서 다운을 받아야한다. 

 

하지만, 드라이버가 왠만한거는 다 안되므로 어떻게 구글링 하다가 메디텍에서 만든 드라이버를 구했더니 설치가 완료되었다.

 

나같은 사람이 또 없기를 바라며 포스팅 한다.

meditek_wlan_ 3.00.01.1239.zip
2.22MB

반응형

'Day Life' 카테고리의 다른 글

2024 하반기 지원 회고  (4) 2025.01.03
2023 회고  (1) 2023.12.31
2022/08/06  (0) 2022.08.06
21.08.13  (0) 2021.08.13
실버 달성  (0) 2021.04.27
반응형

Layout.tsx

import React, {FC} from "react";
import {Stack, Flex, Box, Text, Button} from '@chakra-ui/react';
import { Link } from "react-router-dom";

const Layout: FC = ({children}) =>{
    return( 
    
    <Stack h="100vh">
        <Flex bg="purple.200" p={4} justifyContent="space-around" alignItems="center">
            <Box>
                <Text fontWeight="bold">h662-Animals</Text>
            </Box>
            <Link to="/">
                <Button size="sm" colorScheme="blue">
                    Main
                </Button>
            </Link>
            <Link to="my-animal">
                <Button size="sm" colorScheme="red">
                    My Animal
                </Button>
            </Link>
            <Link to="sale-animal">
                <Button size="sm" colorScheme="green">
                    Sale Animal
                </Button>
            </Link>
        </Flex>
        <Flex direction="column" h="full" justifyContent="center" alignItems="center">
            {children}
        </Flex>
    </Stack>
    );
}

export default Layout

 

MyAnimalCard.tsx

 

import React , {FC, useState, ChangeEvent} from "react";
import {Box, Text, InputGroup, Input, InputRightAddon, Button} from "@chakra-ui/react"
import AnimalCard from "./AnimalCard";
import { saleAnimalTokenContract, web3 } from "../contracts";

export interface IMyanimalCard{
    animalTokenId : string;
    animalType : string;
    animalPrice : string;
}

interface MyAnimalCardProps extends IMyanimalCard {
    saleStatus:boolean;
    account:string;
}

const MyAnimalCard: FC<MyAnimalCardProps> = ({animalTokenId, animalType, animalPrice, saleStatus, account}) =>{
    const [sellPrice, setSellPrice] = useState<string>("");
    const [myAnimalPrice, setMyAnimalPrice] = useState<string>(animalPrice)

    const onChangeSellPrice = (e: ChangeEvent<HTMLInputElement>) =>{
        setSellPrice(e.target.value);
    }

    const onClickSell = async () =>{
        try{
            if(!account || !saleStatus) return;

            const response = await saleAnimalTokenContract.methods
            .setForSaleAnimalToken(animalTokenId, web3.utils.toWei(sellPrice, "ether"))
            .send({from:account});

            if(response.status) {
                setMyAnimalPrice(web3.utils.toWei(sellPrice, "ether"));
                console.log(response)
            }
        }catch(err){
            console.log(err);
        }
    }

    return(
        <Box textAlign="center" w={150}>
            <AnimalCard animalType={animalType} /><Box  mt={2}>
                {animalPrice === "0" ? (
                <>
                    <InputGroup>
                        <Input type='number' value={sellPrice} onChange={onChangeSellPrice}/>
                        <InputRightAddon children="Matic" />
                    </InputGroup>
                    <Button size="sm" colorScheme="green" mt={2} onClick={onClickSell}>
                        Sell
                    </Button>
                </>) : <Text d="inline-block">{web3.utils.fromWei(myAnimalPrice)} Matic</Text> }
            </Box>
        </Box>
    )
}

export default MyAnimalCard;

함수 설명

  1. onChangeSellPrice = (e: ChangeEvent<HTMLInputElement>)
    • Input 박스 내의 요소가 바뀔때마다 price 를 바꿔준다.
  2. onClickSell
    • 토큰을 판매 등록하는 함수

SaleAnimalCard.tsx

import React, {FC, useState, useEffect} from "react";
import AnimalCard from "./AnimalCard";
import {Box, Text, Button} from "@chakra-ui/react"
import { mintAnimalTokenContract, saleAnimalTokenContract, web3 } from "../contracts";

interface SaleAnimalCardProps{
    animalType:string;
    animalPrice:string;
    animalTokenId: string;
    account:string;
    getOnSaleAnimalTokens: () => Promise<void>;
}

const SaleAnimalCard:FC<SaleAnimalCardProps> =({animalType,animalPrice,animalTokenId, account,getOnSaleAnimalTokens}) =>{
    const [isBuyable, setIsBuyable] = useState<boolean>(false);

    const getAnimalTokenOwner = async () => {
        try{
            const response = await mintAnimalTokenContract.methods.ownerOf(animalTokenId).call();
            
            console.log(response)
            console.log(account);
            setIsBuyable(response.toLocaleLowerCase() === account.toLocaleLowerCase())
        } catch(err){
            console.log(err);
        }   
    } 

    const onClickBuy = async () =>{
        try{
            if(!account) return;
            const response = await saleAnimalTokenContract.methods.purchaseAnimalToken(animalTokenId).send({from: account, value:animalPrice});

            if(response.status){
                getOnSaleAnimalTokens();
            }
        } catch(err){
            console.log(err)
        }
    }

    useEffect(() => {
      
        getAnimalTokenOwner();
    }, [])
    

    return(
        <Box textAlign ="center" w={100}>
            <AnimalCard animalType={animalType} />
            <Box>
                <Text d="inline-block">
                    {web3.utils.fromWei(animalPrice)} Matic
                </Text>
                <Button size="sm" colorScheme="green" m={2} disabled={isBuyable} onClick={onClickBuy}>Buy</Button>
            </Box>
        </Box>
    )
}

export default SaleAnimalCard
반응형
반응형

사용할 프레임 워크 : chakra UI

강의에서는 리액트 17 버전을 사용중이기 때문에 차크라 UI 는 1버전으로 다운로드 해줘야 정상 실행된다.

 

 

App.tsx

import React, { FC, useState, useEffect  } from "react";

import { BrowserRouter, Routes, Route} from "react-router-dom"; 
import Layout from "./components/Layout";
import Main from "./routes/main";
import MyAnimal from "./routes/my-animal";
import SaleAnimal from "./routes/sale-animal";

const App: FC = () => {
  const [account, setAccount] = useState<string>("");

  const getAccount = async () => {
    try{
      if(window.ethereum){
        const accounts = await window.ethereum.request({
          method:'eth_requestAccounts',
        })
        setAccount(accounts[0])
      } else{
        alert("Install Metamask");
      }
    }catch(err){
      console.log(err);
    }
  }

  useEffect(() => {
    getAccount();
    console.log(account)
  }, [account])
  

  return (
    <BrowserRouter>
      <Layout>
        <Routes>
          <Route path="/" element={<Main account={account}/>} />
          <Route path="my-animal" element={<MyAnimal account={account}/>} />
          <Route path="sale-animal" element={<SaleAnimal account={account}/>} />
        </Routes>
      </Layout>
      
    </BrowserRouter>
  )
};

export default App;
  • account 가 바뀔때마다 렌더링을 해주는 방식
  • Metamask 설치 유무또한 확인해 주어야한다.

main.tsx

import React , {FC, useState} from 'react';
import {Button, Box, Text, Flex} from '@chakra-ui/react';
import { mintAnimalTokenContract } from '../contracts';
import AnimalCard from '../components/AnimalCard';

interface MainProps {
    account :string;
}

const Main : FC<MainProps> = ({account}) => {
    const [NewAnimalType, setNewAnimalType] = useState<string>("")

    const onClickMint = async () =>{
        try{
            if(!account) return;

            const response = await mintAnimalTokenContract.methods
                                    .mintAnimalToken()
                                    .send({from: account});

            console.log(response);
            if(response.status){
                const balanceLength = await mintAnimalTokenContract.methods
                                    .balanceOf(account)
                                    .call();

                const animalTokenId = await mintAnimalTokenContract.methods
                .tokenOfOwnerByIndex(account, parseInt(balanceLength.length, 10) -1)
                .call();

                const animalType = await mintAnimalTokenContract.methods
                .animalTypes(animalTokenId)
                .call();

                setNewAnimalType(animalType);
                console.log(NewAnimalType);
            }
        }catch(err){
            console.log(err);
        }
    }

    return <Flex w="full" h= "100vh" justifyContent="center" alignItems="center" direction="column">
        <Box>
            {NewAnimalType ? <AnimalCard animalType={NewAnimalType} /> : <Text>Let's mint Animal Card!</Text>}
        </Box>
        <Box>
            <Button mt={4} size="sm" colorScheme="blue" onClick={onClickMint}>Mint</Button>
        </Box>
    </Flex>
}
export default Main;

함수설명

  1. onClickMint
    • 컨트랙트 함수에서 mint 를 호출하여 토큰을 생성하고 토큰의 id, type 을 저장한다.

my-animal.tsx

import React , {FC, useState, useEffect} from "react";
import AnimalCard from "../components/AnimalCard";
import { mintAnimalTokenContract, saleAnimalTokenAddress, saleAnimalTokenContract } from "../contracts";
import {Grid, Box , Button, Text, Flex} from '@chakra-ui/react'
import MyAnimalCard, { IMyanimalCard } from "../components/MyAnimalCard";
interface MyAnimalProps {
    account : string;
}

const MyAnimal : FC<MyAnimalProps> = ({account}) =>{
    const [AnimalCardArray, setAnimalCardArray] = useState<IMyanimalCard[]>();
    const [SaleStatus, setSaleStatus] = useState<boolean>(false);

    const getAnimalTokens = async() => {
        try{
            
            const balanceLength = await mintAnimalTokenContract.methods
            .balanceOf(account)
            .call();

            if(balanceLength =="0") return ;

            const tempAnimalCardArray: IMyanimalCard[] = [];

            const response = await mintAnimalTokenContract.methods.getAnimalTokens(account).call();
            console.log(response)

            response.map((v: IMyanimalCard) => {
                tempAnimalCardArray.push({animalTokenId : v.animalTokenId, animalType : v.animalType, animalPrice : v.animalPrice})
            })
            
            setAnimalCardArray(tempAnimalCardArray);
        }catch(err){
            console.log(err);
        }
    };

    const getIsApprovedForAll = async () =>{
        try{
            const response = await mintAnimalTokenContract.methods
            .isApprovedForAll(account, saleAnimalTokenAddress)
            .call();
            if(response){
                setSaleStatus(response);
            }
            console.log(response);
        }catch(err){
            console.log(err)
        }
    }

    const onClickApproveToggle = async () =>{
        try{
            if(!account) return;

            const response = await mintAnimalTokenContract.methods
            .setApprovalForAll(saleAnimalTokenAddress, !SaleStatus)
            .send({from:account});

            if(response.status){
                setSaleStatus(!SaleStatus);
            }
        }catch(err){
            console.log(err);
        }
    }

    useEffect(() => {
        if(!account) return;
        getAnimalTokens();
        getIsApprovedForAll();
    }, [account])
    
    useEffect(() => {
        console.log(AnimalCardArray)
    }, [AnimalCardArray])

    return(
        <>
        <Flex alignItems="center">
            <Text display="inline-block">
                Sale Status : {SaleStatus ? "True" : "False"}
            </Text>
            <Button size="xs" ml={2} colorScheme={SaleStatus ? "red" : "blue"} onClick={onClickApproveToggle}>
                {SaleStatus ? "Cancel" : "Approve"}
            </Button>
        </Flex>
        <Grid templateColumns ="repeat(4,1fr)" gap={8} mt={2}>
            {
                AnimalCardArray && AnimalCardArray.map((v,i) =>{
                    return <MyAnimalCard key={i} animalTokenId={v.animalTokenId} animalType={v.animalType} animalPrice={v.animalPrice} saleStatus={SaleStatus} account={account}/>;
                }
            )}
        </Grid>
        </>
    );
}

export default MyAnimal

함수 설명

  1. getAnimalTokens
    • account 가 소유한 카드들을 불러와서 배열형태로 리턴한다.
  2. getIsApprovedAll
    • account 와 카드의 주인이 지닌 주소를 비교해 같지 않은지 확인 한다.
    • true 값이 반환되어야 판매등록이 가능하다.
  3. onClickApproveToggle
    • getIsApprovedAll 을 위한 버튼 함수

sale-animal.tsx

import React , {FC, useState, useEffect} from "react";
import {Grid} from "@chakra-ui/react"
import { IMyanimalCard } from "../components/MyAnimalCard";
import { mintAnimalTokenContract, saleAnimalTokenContract } from "../contracts";
import SaleAnimalCard from "../components/SaleAnimalCard";


interface SaleAnimalProps {
    account:string;
}

const SaleAnimal:FC<SaleAnimalProps> = ({account}) =>{
    const [saleAnimalCard, setSaleAnimalCard] = useState<IMyanimalCard[]>()

    const getOnSaleAnimalTokens = async () =>{
        try{
            const getOnSaleAnimalTokenArrayLength = await saleAnimalTokenContract.methods.getOnSaleAnimalTokenArrayLength().call();

            const tempOnSaleArray : IMyanimalCard[] = [];

            for(let i = 0;i<parseInt(getOnSaleAnimalTokenArrayLength, 10); i++){
                const animalTokenId = await saleAnimalTokenContract.methods.onSaleAnimalTokenArray(i).call();

                const animalType = await mintAnimalTokenContract.methods.animalTypes(animalTokenId).call();

                const animalPrice = await saleAnimalTokenContract.methods.animalTokenPrices(animalTokenId).call();

                tempOnSaleArray.push({animalTokenId, animalType, animalPrice})
            }

            setSaleAnimalCard(tempOnSaleArray);
        } catch(err){
            console.log(err);
        }
    }

    useEffect(() => {
      getOnSaleAnimalTokens();
    }, [])
    
  
    

    return(
        <Grid mt={4} templateColumns="repeat(4, 1fr)" gap={8}>
                {saleAnimalCard && saleAnimalCard.map((v,i) => {
                    return <SaleAnimalCard key={i} animalType={v.animalType} animalPrice={v.animalPrice} animalTokenId={v.animalTokenId} account={account} getOnSaleAnimalTokens={getOnSaleAnimalTokens}/>
                })}
        </Grid>
    );
}

export default SaleAnimal

함수 설명

  1. getOnSaleAnimalTokens
    • 판매중인 토큰들을 불러오는 함수
    • my-animal 과 같이 컨트랙트에서 배열을 받아오면 되지만 강의에서는 귀찮아서 for문으로 했다.
반응형

'BlockChain > Solidity' 카테고리의 다른 글

[zkSync] 간단하게 다뤄보기  (0) 2025.01.11
[DP/NFT] 3. SaleAnimalToken 작성  (0) 2022.09.05
[DP/NFT] 2. Minting contract 작성  (0) 2022.09.05
[DP/NFT] 1. Install Solidity & Metamask  (0) 2022.08.25

+ Recent posts