AWS Lambda python 3.12 전환

Study Plan 2024. 1. 22. 21:13

Lambda 에서 python 3.4 -> 3.12 전환하며 발생한 문제점

 

1. No Module named 'pydantic_core._pydantic_core' 발생

 - 기존에 사용하지 않았던 pydantic 모듈 에러가 갑자기 발생(무슨 모듈인지도 모른다...)

 - 기존에 labmda가 잘 돌아가고 있었고, 추가로 한 작업은 아래와 같다

1. 노트북 -> 데스크톱으로 작업환경을 변경했기에 신규 Python 3.12 버전 설치
2. 기존에 lambda에서 사용하던 site-packages를 다운로드
3. 사용하는 모델이 deprecated됨에 따라 openAI 사용 API 변경
   - 모델 엔진 : text-davinci-003 -> gpt-3.5-turbo-1106
   - 사용 함수 : openai.Completion -> chat.completions
4. openAI 신규 모듈 설치
5. 신규 openAI 모듈을 2번에서 받은 site-packages에 복사
6. zip으로 압축하여 신규 Layer 생성
7. gpt-3.5-turbo-1106 모델을 사용하는 python 코드 lambda에 deploy
8. 변경된 Layer로 labmda 수행

 - 복잡한 작업은 없기에 당연히 수행이 완료될 줄 알았으나 pydantic 오류가 발생했다.

 

AWS lambda가 python 3.12를 지원하기 시작한게 2023.12월이기에 이제 막 한달이 지난 시점이다.
이 때문에 발생하는 오류인가???
> 응 아니야

 

 

열심히 구글링 한 결과 비슷한 오류를 겪는 사용자들이 있던 것을 발견!!

 - https://github.com/pydantic/pydantic/issues/6557

 

No module named 'pydantic_core._pydantic_core' using AWS Lambdas · Issue #6557 · pydantic/pydantic

Initial Checks I confirm that I'm using Pydantic V2 installed directly from the main branch, or equivalent Description I have pydantic 2.0.2 installed into my AWS Lambda with python3.10 and wheneve...

github.com

 

문제의 원인은 pip로 설치한 모듈의 아키텍쳐가 lambda에서 설정한 아키텍쳐와 달라서 발생한 문제이다!!!
AWS Lambda에서 python 3.12는 arm64 버전으로 구동을 지원한다.
*로컬에서 pip install pydantic 으로 모듈 설치 시 arm64가 아닌 x86 아키텍처로 모듈이 설치되고 있었다.

 

AWS 내 Python 버전별 지원 현황

 

 

내게 발생한 문제는 pydantic_core 문제이므로 관련된 pydantic* 패키지들을 arm64 아키텍처로 설치하면 된다.

가이드 문서에도 나와 있는 형태로 모듈을 설치하면 된다

#pydantic arm64 설치
pip install --platform manylinux2014_aarch64 --target=package --implementation cp --python-version 3.12 --only-binary=:all: --upgrade pydantic==2.5.3

#pydantic-core arm64 설치
pip install --platform manylinux2014_aarch64 --target=package --implementation cp --python-version 3.12 --only-binary=:all: --upgrade pydantic_core=2.14.6

 

*pydantic 모듈 설치 후 lambda에서 동작할 수 있도록 작업해주면 된다.

 - site-packages를 zip으로 압축하면 된다. (.zip으로 계층을 생성하는 경우 python\python\모듈들.. 형태로 압축해야한다)

 - lambda > 계층 > 본인 Lambda Function > 버전 생성 으로 신규 계층을 생성한다.

계층 생성

 

 

 

*참고) arm64 모듈 설치 AWS 가이드 https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/python-package.html#python-package-native-libraries

 

Python Lambda 함수에 대한 .zip 파일 아카이브 작업 - AWS Lambda

배포 패키지 또는 계층의 종속 항목이 런타임 포함 라이브러리보다 우선하므로 SDK도 포함하지 않고 패키지에 urllib3과 같은 SDK 종속 항목을 포함하면 버전 불일치 문제가 발생할 수 있습니다. 자

docs.aws.amazon.com

 

 

 

'Study Plan' 카테고리의 다른 글

티스토리 API와 Open AI Model 만료에 따른 수정사항 정리  (117) 2024.01.21
AI 이모저모  (11) 2023.08.09
티스토리 자동화를 위한 Step2 고민  (14) 2023.07.31
커리어 플랜  (0) 2023.05.02

티스토리 API와 Open AI Model 만료에 따른 수정사항 정리

Study Plan 2024. 1. 21. 13:50

1. 티스토리 Open API 종료

 - 2월 말까지 순차적으로 종료될 예정

https://notice.tistory.com/2664

 

[안내] 티스토리 Open API가 종료됩니다.

안녕하세요. 티스토리팀입니다. 티스토리 기능을 외부에서 제어하고, 티스토리를 이용해 서비스 개발을 할 수 있도록 제공한 티스토리 Open API가 종료될 예정입니다. 이에 따라 Open API를 활용한

notice.tistory.com

 - 왜 종료하는가에 대한 의문은 있다..

 - 타 플랫폼은 지원하는데 티스토리만 api 지원을 중단하는게 참으로 안타깝다 (브런치 플랫폼을 활성화하고자 카카오에서 버리려는 것 일수도?)

 - 여튼 현재 작성하고 있는 billboard 파헤치기는 api 지원 종료 시점부터 자동 글쓰기가 불가능하므로 다른 방법을 찾아봐야겠다.

 

2. Open AI 모델 deprecated

 - 티스토리 API 가 종료되지 않았는데도 billboard 파헤치기 글이 작성되지 않고 있었다. 확인해보니 내가 사용중이던 모델이 더이상 지원되지 않는다고 한다. (현재 사용 중인 모델은 text-davinci-003 이다.)

 - 2월에 종료될 예정이나.. python과 open AI api 공부나 할 겸 새로운 모델인 gpt-3.5-turbo-1106를 적용해 보도록 하자

 - text-davinci-003 에서 gpt-3.5-turbo-1106 모델로 바뀜에 따라 API 사용방식에 많은 변화가 생겼으므로 고려할게 많아졌다.

 

# Asis openai api 사용법 (completion)

openai.api_key = "API Key" # Replace with your API key
    # 모델 엔진 선택
    model_engine = "text-davinci-003"

    # 맥스 토큰
    max_tokens = 2048

    # 블로그 생성
    completions = openai.Completion.create(
        engine=model_engine,
        prompt=prompt,
        max_tokens=max_tokens,
        temperature=0.3,      # creativity
        top_p=1,
        frequency_penalty=0,
        presence_penalty=0
    )
# Tobe openai api 사용법 (Chat)

from openai import OpenAI
client = OpenAI()

response = client.chat.completions.create(
  model="gpt-3.5-turbo-1106",
  messages=[
    {
      "role": "user",
      "content": ""
    }
  ],
  temperature=1,
  max_tokens=256,
  top_p=1,
  frequency_penalty=0,
  presence_penalty=0
)

 

3. Todo List

 - 데스크톱에 python 환경세팅

 - open ai 의 chat api 사용법 확인

 - 기능 구현 확인 및 테스트

 - 현재 AWS의 lambda로 자동 글쓰기 스케쥴링을 걸어놓았으므로 업데이트

   > 다만, asis 환경은 python 3.2 버전이고 신규 openai는 3.7 이상 필요하므로 lambda의 python 환경설정도 업데이트 해줘야함

 - vue 공부도 더 해야함~

'Study Plan' 카테고리의 다른 글

AWS Lambda python 3.12 전환  (111) 2024.01.22
AI 이모저모  (11) 2023.08.09
티스토리 자동화를 위한 Step2 고민  (14) 2023.07.31
커리어 플랜  (0) 2023.05.02

java 8 정리1

Java 정리 2021. 5. 12. 21:43

인프런 강의 4일차. 

 - 더 자바, Java 8 (백기선 강사님)

 

1. 함수형 인터페이스

 - 추상 메소드를 딱 하나만 가지고 있는 인터페이스

 - SAM (Single Abstract Method) 인터페이스

 - @FunctionInterface 애노테이션을 가지고 있는 인터페이스

 

2. 람다 표현식

 - 함수형 인터페이스의 인스턴스를 만드는 방법으로 쓰일 수 있다.

 - 코드를 줄일 수 있다.

 - 메소드 매개변수, 리턴타입, 변수로 만들어 사용할 수도 있다.

 

3. 자바에서 함수형 프로그래밍

 - 함수를 First Class Object로 사용할 수 있다.

 - 순수 함수(Pure Function) 

    -> 사이드 이펙트 만들 수 없다. (함수 밖에 있는 값을 변경하지 못한다)

    -> 상태가 없다. (함수 밖에 정의되어 있는)

 - 고차 함수(High-Order Function)

    -> 함수가 함수를 매개변수로 받을 수 있고, 함수를 리턴할 수도 있다.

 - 불변성

 

4. 단축키

 -> Alt + Enter : 익명 내부 클래스를 람다로 바꿔주는 단축키(IntelliJ)

package me.whiteship.java8to11;

@FunctionalInterface
public interface RunSomething {

    //추상 메소드가 1개만 있다면 함수형 인터페이스
    //다른 구현된 메소드가 여러개이더라도 추상화 메소드가 1개라면 함수형 인터페이스
    // @FuncationalInterface 추가 시 함수형 인터페이스로 취급되어 추상 메소드 1개만 선언이 가능하다.
    //void doIt();
    int doIt(int number);

    //static method 정의 가능
    static void printName(){
        System.out.println("dhpark");
    }

    //default method 정의 가능
    default void printAge(){
        System.out.println("32");
    }

}


package me.whiteship.java8to11;

public class Foo {

    public static void main(String[] args) {

        //익명 내부 클래스 anonymous inner class
        /*
        RunSomething runSomething = new RunSomething() {
            @Override
            public void doIt() {
                System.out.println("Hello");
            }
        };

        //Alt + Enter : 익명 내부 클래스를 람다 표현식으로 바꿔주는 자동완성 기능
        RunSomething runSomething = () -> System.out.println("Hello");
        runSomething.doIt();
         */
        /*
          함수형 인터페이스를 인라인으로 구현한 오브젝트라고 볼 수 있다.
          이러한 형태는 java가 객체지향 언어이기 때문에 아래 스텝으로 처리된다.
          1. System.out.println("Hello");를 runSomething 객체에 할당
          2. runSomething 객체를 메소드 파라미터에 전달
          3. doIt() 메소드 실행
          위와 같은 호출을 First Class Object로 사용한 것으로 본다.
         */


        /*
          순수 함수 : 입력받은 값이 동일한 경우 결과 값이 같아야 한다.(수학적인 의미)
          아래와 같은 경우 Pure하다 라고 볼 수 없다. (상태 값에 의존한다 라고 볼 수 있다)
           - Case1. 함수가 함수 바깥의 변수를 가져다 사용하는 경우
           - Case2. 외부의 값을 변경하려는 경우
         */
        //1. 순수 함수
        RunSomething runSomething1 = (number) -> {
            return number + 10;
        };
        System.out.println(runSomething1.doIt(1));

        //2. 순수 함수가 아닌 경우
        int baseNumber1 = 10;    //함수 바깥의 변수
        RunSomething runSomething2 = new RunSomething() {
            int baseNumber2 = 20;    //함수 바깥의 변수

            @Override
            public int doIt(int number) {
                baseNumber2++;  //Case2. 외부의 값을 변경하려는 경우
                return number + baseNumber1;    //Case1. 함수 바깥의 값을 가져다 사용하는 경우
            }
        };
    }
}

 

5. Java가 기본으로 제공하는 함수형 인터페이스

 - Java.lang.function 패키지

 - 자바에서 미리 정의해둔 자주 사용할만한 함수 인터페이스

 - Function<T, R>

 - BiFunction<T, U, R>

 - Consumer<T>

 - Supplier<T>

 - Predicate<T>

 - UnaryOperator<T>

 - BinaryOperator<T>

 

6. Function<T, R>

 - T 타입을 받아서 R 타입을 리턴하는 함수 인터페이스

   -> R apply(T t)

 - 함수 조합용 메소드

   -> andThen

   -> compose

 

7. BiFunction<T, U, R>

 - Function<T, R>와 유사하나, 입력값을 2개 받는다.

 - 두 개의 값 (T, U)를 받아서 R 타입을 리턴하는 함수

    -> R apply(T t, U u)

 

8. Consumer<T>

 - T 타입을 받아서 아무것도 리턴하지 않는 함수 인터페이스

   -> void Accept(T t)

 - 함수 조합용 메소드

   -> andThen

 

9. Supplier<T>

 - T 타입의 값을 제공하는 함수 인터페이스

   -> T Get()

 

10. Predicate<T>

 - T 타입의 값을 받아서 boolean을 리턴하는 함수 인터페이스

   -> boolean test(T t)

 - 함수 조합용 메소드

   -> And

   -> Or

   -> Negate

 

11. UnaryOperator<T>

 - Function<T, R>의 특수한 형태로, 입력값 하나를 받아서 동일한 타입을 리턴하는 함수 인터페이스

 

12. BinaryOperator<T>

 - BiFunction<T, U, R>의 특수한 형태로, 동일한 타입의 입력값 두개를 받아 리턴하는 함수 인터페이스

 

package me.whiteship.java8to11;

import java.util.function.*;

public class Foo {

    public static void main(String[] args) {
        //1. 클래스를 만들어서 함수형 프로그래밍
        /*
        public class Plus10 implements Function<Integer, Integer> {
            @Override
            public Integer apply(Integer integer) {
                return integer + 10;
            }
        Plus10 plus10 = new Plus10();
        System.out.println(plus10.apply(1));
         */

        //2. 람다 형식으로 함수형 프로그래밍1 (apply)
        /*Function<Integer, Integer> plus10 = (i) -> i+10;
        System.out.println(plus10.apply(2));*/

        //2. 람다 형식으로 함수형 프로그래밍2 (compose, andThen)
        // Compose : 가지고 뒤에 오는 함수 적용하여 계산 후 src의 입력 값으로 사용
        Function<Integer, Integer> plus10 = (i) -> i+10;
        Function<Integer, Integer> multiply2 = (i) -> i * 2;

        //plus10.compose(multiply2);  //multiply2 적용 후 plus10 하겠다는 의미
        Function<Integer, Integer> multiply2AndPlus10 = plus10.compose(multiply2);
        System.out.println(multiply2AndPlus10.apply(2)); // 10 + (2 * 2)

        // andThen : 앞의 값 계산 후 뒤의 입력 값으로 사용 (compose와 반대)
        Function<Integer, Integer> plus10AndMultiply2 = plus10.andThen(multiply2);
        System.out.println(plus10AndMultiply2.apply(2)); // (2 + 10) * 2


        Consumer<Integer> printT = (i) -> System.out.println(i);
        printT.accept(10);      //10 출력

        Supplier<Integer> get10 = () -> 15;
        System.out.println(get10.get());    //15 출력

        Predicate<String> startsWithPark = (s) -> s.startsWith("Park");
        //Predicate<Integer> isEven = (i) -> i%2 == 0;
        System.out.println(startsWithPark.test("Park"));


        // 같은 타입의 인풋, 아웃풋인 경우 UnaryOperator를 써서 좀 더 깔끔하게 처리 가능
        //Function<Integer, Integer> plus10 = (i) -> i+10;
        UnaryOperator<Integer> unaryPlus10 = (i) -> i+10;

        // BiFunction은 3개의 타입이 전부 다를 때 사용하고, BinaryOperator 는 3개의 타입이 전부 같을 때 사용한다.
    }
}

 

14. 람다 표현식

package me.whiteship.java8to11;

import java.util.function.*;

public class Foo {

    public static void main(String[] args) {
        Foo foo = new Foo();
        foo.run();
    }

    private void run() {
        final int  baseNumber = 10;

        // 로컬 클래스
        class LocalClass {
            void printBaseNumber(){
                int baseNumber = 11;    //섀도잉
                System.out.println(baseNumber); // 11 출력
            }
        }


        // 익명 클래스
        Consumer<Integer> integerConsumer = new Consumer<Integer>() {
            @Override
            public void accept(Integer baseNumber) {        //baseNumber 변수는 파라미터로 넘어온 baseNumber를 사용하게 됨 = 섀도잉
                System.out.println(baseNumber); //익명 클래스에서 로컬 변수 참조하는 법
            }
        };

        // 람다
        IntConsumer printInt = (i) -> {
            System.out.println(i + baseNumber);
        };

        printInt.accept(30);

        /*
         3개 클래스 모두 공통적으로 로컬 변수를 참조할 수 있다.
         java8 부터 final을 생략할 수 있는 경우가 있는데 해당 변수가 사실상 final인 경우 생략이 가능하다.
         사실상 fianl 의미 : 변수 선언 후 값을 변경하는 로직이 없는 경우 (= effective fianl)

         람다가 다른 부분은 다른 2개 클래스와 다르게 섀도잉이 불가능하다.
          -> 로컬 클래스나 익명 클래스에서 선언한 변수들은 해당 클래스 바깥 혹은 Nested 클래스에서 같은 이름의 변수 사용이 가능하다(덮어써짐 = 섀도잉)
          즉 람다는 섀도잉이 안되니 람다의 스콥은 람다를 감싸고 있는 클래스와 동일하다
          그렇기 때문에 람다에서 참조 가능한 로컬 변수는 fianl과 effective final 만 사용이 가능하다.(아닐 시 컴파일 에러)

            IntConsumer printInt = (baseNumber) -> {        //람다는 섀도잉이 안되므로 파라미터 이름을 baseNumber로 넘겨주어도 사용이 불가능하다(컴파일 에러 발생)
                System.out.println(baseNumber);
            };
         */
    }
}

'Java 정리' 카테고리의 다른 글

java 8 정리6  (0) 2021.05.21
java 8 정리5  (0) 2021.05.20
java 8 정리4  (0) 2021.05.19
java 8 정리3  (0) 2021.05.17
java 8 정리2  (0) 2021.05.13