오페라는 웹브라우저이다. 내 기억으로는 Chrome 보다 더 오래 되었다. 2000년대 초반 많은 사이트들이 IE(인터넷익스플로러) 기준으로 제작되었다. 그 때 이 브라우저가 리눅스에서 설치되면서 IE전용 사이트에서 괜찮은 호환성을 보였다. 그 때 사용한 브라우저로 요즘은 firefox 와 chrome 만을 사용했는데 AI 기능 때문에 다시 설치해 보았다. 

 왜 갑자기 AI 기능이 추가 되었는지 모르겠지만 이 기능이 다른 AI 보다 실시간성 반영성이 좋다. 일반적인 LLM들은 이미 학습된 데이터들에 대해서만 대답한다. 학습이후 수집한 데이터는 잘 대답하지 못한다. 

 내가 가장 하고 싶은 것은 `오늘 최신 뉴스 브리핑 해줘` 이다. 구글 gemini  무료 버전의 경우 이런 것을 지원해 주지 않는다. chatgpt 무료 버전도 이것을 지원하지 않는다. 그런데 오페라 AI Aria 는 이것을 지원한다. 물론 좀 말의 이해력이 부족한 것 같다. 말을 잘 이해하지 못하면 계속 플로우차트를 생성하려고 한다. 그리고 대화의 세션을 잘 유지 못하는 것 같다. (물론 이것은 내가 로그인하지 않고 사용하는 것도 이유 중 하나 같기는 하다.) 

 이런 쪽에 가장 좋은 것이 perplexity 인 것 같긴 한데, 무료로 사용하면 사용회수 제한이 있다. 오페라 AI 는 그런 제약사항이 없다. 계속 시도해도 된다. 다만 이거 설치가 필요하다. 오페라는 PC버전도 있고 안드로이드 폰 버전도 존재한다. 안드로이드 폰 버전에서도 AI 사용이 가능하다. 

 보고 있는 웹페이지 정보와 연동될 수 있으면 좋을 것 같은데, 아직 그런 기능은 없다. (모바일에서 웹페이지 요약하기 기능은 있다. PC에는 이 기능이 있는지 모르겠다.). 계속 기능이 추가되고 AI 기능이 좋아진다면 내 main 브라우저를 Opera 로 변경할 수도 있을 것 같다. 

 Github 에 있는 남의 코드를 읽다보면 FIXME, TODO 같은 것을 간혹 발견할 수 있다. 평소에 이런 주석을 많이 보기는 했지만 적극적으로 이용하지는 않았는데, 앞으로 이를 적급적으로 활용하는게 좋을 것 같아서 이런 코드를 찾아 봤다.

따로 정리된 규칙이 있는지 찾아 봤는데, 딱히 없는 것 같다. 그래도 가장 정리는 된 문서는 https://peps.python.org/pep-0350/ 이거 같다. 

*  FIXME : 깔끔하지 않는 코드라서 정리가 필요한 코드
* TODO : 처리해야 하는 작업,  보통 함수 이름만 만들어 두고 내부는 TODO로 하는 식으로 처리하는 것 같다. 
* HACK : 버그를 수정하기 위한 유연하지 못한 방법, (알려진 버그 하나만을 처리하기 위한 좀 무식한 코드나 꼼수에 사용하는 것 같다. )
여기 까지가 사람들이 가장 많이 사용하는 codetag 인 것 같고, 다음 codetag 들은 잘 사용하면 유용할 것 같다.

* SEE : 참고해야할 다른 코드나 문서 URL 을 표시할 때
* NOTE : 코드를 리뷰하는 사람이 다는 코멘트
* !!! : 주의, 경고 사항 
* ??? : 알 수 없음. 물음.   (가끔 내가 작성한 코드이긴 하나 왜 이런 코드가 들어가 있지 하고 생각할 때 추가할만하다.)
* BUG : 버그,(알고 있는 버그인데 특수한 사항에만 적용되는 경우라서 알고 있는데, 딱히 수정하지 않을 때 사용할만 하다. )
* PORT : 호환성 문제(개발환경에서만 문제가 된다든지, 배포 환경에서만 동작한다든지에 관한 사항)

크롬 127 부터 window.ai 기능이 실험적으로 도입되었다. 이 기능을 이용해서 간단한 AI 기능을 사용할 수 있다. 실험적 기능이라 모두에게 적용되는 것은 아니고 세팅이 좀 복잡하다. 

https://dev.to/grahamthedev/windowai-running-ai-locally-from-devtools-202j   사이트에 제시되는 방법을 사용해서 빠르면 10분(내 윈도우즈 PC는 설정후 10분 후에 사용이 가능했다.), 느리면 3~4일(내 회사 Intel Macbook은 토~일 요일 포함 4일 정도 소요 되었다. ) 후에 window.ai 기능을 사용할 수 있다. 

 매우 간단하 nano AI 기능이다. WebGPU 를 사용하기 때문에 좋은 그래픽 카드를 사용하면 가속을 받을 수 있다. Chrome 이 어떤 그래픽 카드까지 지원하는지 알 수 없으나 엔비디아는 확실히 지원하는 것 같다. 

저기에 표시된 API 가 어느 순간 변경되어 버렸다. 

// 초기 버전
const chatSession = await window.ai.createTextSession()

// 현재 동작하는 버전
const chatSession = await window.ai.assistant.create()
 

둘 중에 어느 것이 동작하는지 확인이 필요하다. (beta 기능도 아닌 실험적인 기능이라서 빠르게 API가 변경된 것 같다.) 

인터넷에 찾아보니 사람들은 `Gemma 2B 2b-it-gpu-int4` 모델을 활용하는 거라고 추정하고 있다. 이 주소에서 https://www.kaggle.com/models/google/gemma/tfLite/gemma-2b-it-gpu-int4  에서 다양한 형태로 다운받을 수 있다.   
(chrome 에 있는 것은 gemini nano 로 보인다.  https://huggingface.co/oongaboongahacker/Gemini-Nano  에 누가 올려났다.  )

 


대충 코드를 만들었는데, 아래 처럼 하면 1번은 대화가 가능한 것 같다. 물론 대화 세션이 유지되게 하려면 좀 다른 방법이 필요한 것 같다. 그것까지는 잘 모르겠다. 

<!DOCTYPE html>
<html>
  <head>
    <title>Test </title>
  </head>

  <body>
    <textarea id="promp_area" rows="8" style="width: 800px;"></textarea>
    <br/>
    <button  id="ask_btn">ASK</button>
    <br/><br/><br/><br/>
    <textarea id="promp_result" rows="16" style="width: 800px;"></textarea>

    <script>
      let chatSession;
      const start = async function(){
        chatSession = await window.ai.assistant.create();
      }
      start();
      
      async function ask(){
        console.log("==== ask start ====")
        let promp_area = document.getElementById("promp_area");
        let promp_result = document.getElementById("promp_result");

        let promp_text = promp_area.value;
        const stream = chatSession.promptStreaming(promp_text);
        let result = "==== start ====\n"
        let previous = '';

        for await (const chunk of stream) {
          const sub_result = chunk.slice(previous.length);
          console.log(sub_result);
          result += sub_result;
          previous = chunk;
          promp_result.value = result;
        }
        result += "\n==== end ===="
        promp_result.value = result;

        console.log("==== ask end ====")
      }

      const ask_btn = document.getElementById("ask_btn");
      ask_btn.onclick = ask;

      let promp_area = document.getElementById("promp_area");
      promp_area.onkeydown = function(event){
        const isAlt = event.altKey || event.metaKey;
        if(event.key == "Enter"  &&  isAlt){
          ask();
        }
      };



    </script>
  </body>

</html>

 

javascript 코드를 물어 봤는데, 실제로 동작하는 코드를 만들어 냈다. 
```자바스크립트 함수가 필요해. 특정 숫자를 입력으로 받고 소수인지 판단하는 isPrimeNumber 라는 함수를 만들어줘.```
라고 질문하자.아래 코드를 만들어 주었다. 

==== start ====
 ```js
function isPrimeNumber(num) {
  // 1과 같은 숫자는 소수가 아니다
  if (num === 1) {
    return false;
  }

  // 2부터 루트까지 소수 판별
  for (let i = 2; i * i <= num; i++) {
    if (num % i === 0) {
      return false;
    }
  }

  // 소수
  return true;
}
```
==== end ====

이 코드 실제로 잘 동작했다. 


그리고 더 나가서 
```
자바스크립트 함수가 필요해. 특정 숫자를 입력으로 받고 소수인지 판단하는 isPrimeNumber 라는 함수를 만들어줘. 가능한 효율적으로 만들어줘.
```
라고 질문했더니 아래 코드를 만들었다. 

==== start ====
 ```js
function isPrimeNumber(num) {
  // 1과 같은 숫자는 소수가 아니다
  if (num === 1) {
    return false;
  }

  // 2부터 루트까지 소수 판별
  for (let i = 2; i * i <= num; i++) {
    if (num % i === 0) {
      return false;
    }
  }

  // 소수 판별 루트 단위로 
  let 판별 = Math.sqrt(num).floor();
  for (let i = 3; i * i <= 판별; i += 2) {
    if (num % i === 0) {
      return false;
    }
  }

  // 소수 판별
  return true;
}
```
==== end ====

이건 Math.sqrt(num).floor() 이 구문에서 에러가 발생했다. 의도는 충분히 알 것 같다. 
(몰랐는데 크롬 javascript 에서 한글 변수가 동작하네!!! 이건 몰랐다.) 

이 정도면 초보 프로그래머 수준은 되는 것 같다. 


물론 애도 세종대왕 맥북 던짐 사건에는 헛소리 한다. 
```
세종대왕 맥북프로 던짐 사건 알려줘.
```

==== start ====
 **세종대왕 맥북프로 던짐 사건**
세종대왕 맥북프로 던지기 사건은 1998년 9월 27일에 일어난 사건이다. 이 사건은 세종대왕이 맥북프로를 땅에 던져버린 것으로 알려져 있다.

이 사건의 배경에는 1997년 11월 10일에 일어난 세종대왕 유비리 폭행사건이 있다. 세종대왕 유비리 폭행사건은 세종대왕이 유비리에게 폭행을 가한 것으로 알려져 있다. 이 사건 이후 세종대왕은 폭력적이고 잔혹한 통치자로 널리 널렸다.

세종대왕 맥북프로 던지기 사건은 세종대왕이 폭력적이고 잔혹한 통치자로 널리 널리 널렸다는 것을 보여준 사건이다.
==== end ====

 

아직 API 가 변경중에 있고, 모델도 변경가능한 상태라 어떻게 일괄성을 유지해서 개발에 이용할 수 있을지는 잘 모르겠다. 그래도 생각보다 AI가 가까이 있다고 느껴지게 된다.