<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>g_bintree.log</title>
        <link>https://velog.io/</link>
        <description>그냥 합니다</description>
        <lastBuildDate>Tue, 09 Jan 2024 17:07:02 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>g_bintree.log</title>
            <url>https://velog.velcdn.com/images/g_bintree/profile/59dd22ac-4df0-4a0f-9a95-7bf9fa92bf2e/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. g_bintree.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/g_bintree" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[AI Cover에 대한 개인적인 생각 [1]- 아티스트의 브랜드 가치는 사라지지 않는다.]]></title>
            <link>https://velog.io/@g_bintree/AI-Cover%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B0%9C%EC%9D%B8%EC%A0%81%EC%9D%B8-%EC%83%9D%EA%B0%81-1-%EC%95%84%ED%8B%B0%EC%8A%A4%ED%8A%B8%EC%9D%98-%EB%B8%8C%EB%9E%9C%EB%93%9C-%EA%B0%80%EC%B9%98%EB%8A%94-%EC%82%AC%EB%9D%BC%EC%A7%80%EC%A7%80-%EC%95%8A%EB%8A%94%EB%8B%A4</link>
            <guid>https://velog.io/@g_bintree/AI-Cover%EC%97%90-%EB%8C%80%ED%95%9C-%EA%B0%9C%EC%9D%B8%EC%A0%81%EC%9D%B8-%EC%83%9D%EA%B0%81-1-%EC%95%84%ED%8B%B0%EC%8A%A4%ED%8A%B8%EC%9D%98-%EB%B8%8C%EB%9E%9C%EB%93%9C-%EA%B0%80%EC%B9%98%EB%8A%94-%EC%82%AC%EB%9D%BC%EC%A7%80%EC%A7%80-%EC%95%8A%EB%8A%94%EB%8B%A4</guid>
            <pubDate>Tue, 09 Jan 2024 17:07:02 GMT</pubDate>
            <description><![CDATA[<h3 id="intro">Intro</h3>
<p>필자는 23년 7월부터 좋아하는 가수의 AI 모델을 만들고 커버곡을 생성하여 유튜브에 업로드하는 활동을 6개월간(글 작성시점 - 24년 1월) 이어오고 있다.</p>
<p>조회수가 1만회를 돌파한 영상이 처음으로 탄생했고, 일명 &#39;신청곡&#39;을 실제 가수가 아닌 나에게 부탁하는 댓글이 달리기 시작했다. 내가 작업해서 업로드한 &#39;신청곡&#39;이 해당 가수의 팬의 마음에 들면 댓글에 하트를 한가득 붙여서 나한테 고마움을 전한다. (마음에 들지 않으면 냉정하게 별로라고 댓글을 달기도 한다.)</p>
<p> AI 음악을 소비하는 사람들과 이러한 묘한(?) 방식으로 직접 소통하던 필자는, 목소리 변환 AI의 성능을 따지는 것 외에도 컨텐츠 측면에서 탐구할 흥미로운 부분이 많다는 것을 느꼈다. </p>
<h3 id="000가-커버하는-xxxx을-듣고-싶어요">&quot;000가 커버하는 XXXX을 듣고 싶어요!&quot;</h3>
<p>가장 자주 달리는 댓글이다. </p>
<p>많은 사람들이 본인이 좋아하는 가수가 어떤 곡을 부를 때 이렇게 표현하지 않을까? 라는 상상을 한다. 그리고 AI 모델로 이를 현실감있게 실현하였을 때 대리만족을 느끼는 모습을 관찰할 수 있다. </p>
<p>단순히 노래를 잘 하는 AI가 만든 음악을 듣고 싶은게 아니다. 내가 좋아하는 &#39;바로 그 가수&#39;가 직접 부른 듯한 노래를 듣고 싶은 것이다. </p>
<p> 큰 사랑을 받는 아티스트들은 음악 외적인 측면에도 확실한 정체성이 있다. 가수로 성공하기까지 역경을 극복한 스토리, 또는 외형적인 매력, 또는 미디어에 노출된 사람으로서의 매력, 또는 일명 스타성/무대장악력이라고 표현되는 무대 위의 퍼포먼스 등등등. </p>
<p> 가수의 음색, 곡 해석능력, 표현능력, 무대매너 등의 음악적 역량이 큰 비중을 차지하겠지만 특정 아티스트를 사랑하는 팬의 마음은 위에 언급한 노래 외적인 것들이 종합적으로 스며있을 것이다. 이것이 아티스트의 &#39;브랜드&#39;이고, AI 커버곡들의 흥행 (높은 조회수)을 결정 짓는 것은 바로 이 &#39;브랜드&#39;가 사람들의 머릿속에 자동적으로 그려지게 하는가의 여부이다. </p>
<h3 id="아티스트는-살아있는-groundtruth">아티스트는 살아있는 GroundTruth</h3>
<p>AI Cover 생성 모델은 특정 아티스트와 최대한 똑같이 곡을 표현해야한다는 임무를 갖고 학습을 거친다.</p>
<p>그런데 AI 모델에 학습 데이터를 제공할 수 있는 출처는 유일무이하게 바로 그 아티스트뿐이다. 특정한 한 사람만이 독점적으로 자신의 생득적인 음색과 창법을 AI 모델에 학습자료로 제공할 수 있다. </p>
<p>기존 AI의 대표적인 사례는 사람의 인지능력을 모방하는 것이 많았다. 물체인식, 음성인식, text 해석 등의 작업을 수행하고 이때 AI가 내놓는 결과물은 객관적으로 참/거짓 여부를 판별할 수 있는 류의 것이다. </p>
<p>반면 커버곡 생성 AI는 이와 다르다. AI 커버곡이 학습을 타겟으로 한 아티스트와 얼마나 유사한지는 해당 아티스트의 리스너들이 1차적으로 판단한다. 내 유튜브 채널에 달리는 댓글 피드백들을 보면 어떤 이들은 만족하고 어떤 이들은 실제 아티스트 같지 않다고 아쉬움을 표한다. 즉 각각의 사람들이 조금씩 다르게, 주관적으로 상상하던 &#39;정답&#39;이 복수로 존재하는 것이다.  </p>
<p>만약 실제 아티스트가 등판하여 AI로 생성되었던 곡을 본인이 직접 부른다면? AI 커버곡들은 바로 무용지물이 될 것이다. 사람들이 마음속에 상상만 하던 것이 실현되었는데 그저 &#39;흉내&#39;낼 뿐인 AI 커버곡을 더 이상 들을 이유가 없지 않겠는가. 그리고 아마도 실제 아티스트의 커버곡을 기준으로 AI 커버곡들을 채점하며 얼마나 유사한지에 따라 점수가 매겨질 것이다. </p>
<h3 id="결론--아티스트의-가치는-더더욱-높아질-것">결론 : 아티스트의 가치는 더더욱 높아질 것</h3>
<p>가수들이 AI 커버곡들을 보며 당혹스러워하는 리뷰 영상을 종종 본다. 본인들이 얼마나 많이 노력하고 연습해서 가수가 되었는데, AI는 이렇게 쉽게 해버린다며 현타를 느끼는 듯 보였다.  </p>
<p>그러나 AI가 정말 간절히 원하는 학습데이터를 본인의 생득적인 능력을 기반으로 독점적으로 제공할 수 있다는 것은 현시대에 엄청난 메리트이다. AI가 따라하고자 하는 살아있는 GroundTruth 존재는 아무나 될 수 있는 것이 아니다. 요즘 세상에 대부분의 사람들은 AI에게 가치있는 대상이 아니다.  AI가 제발 당신을 따라하고 싶으니 학습데이터 좀 달라고 요청하는 사람은 극소수일 것이다. </p>
<p>현 시점에서는 특정 모델이 어떤 가수의 목소리와 곡을 기반으로 학습되었는지 추적하는게 쉽지 않다. 그러나 앞으로는 분명히 이미지 파일의 워터마크와 같이 데이터 출처를 각인시킬 수 있는 기술과 제도가 등장할 것이다. 이후에는 사람의 생득적인 특성에 부여되는 새로운 형태의 저작권이 적용될 것이다. </p>
<p>짧은 견해이지만, 아티스트들은 AI 커버곡이 대중화되는 것이 본인들에게 큰 기회라고 생각하면 될 것 같다. AI로 대체되기는 커녕 오히려 본인의 차별화된 목소리와 음악적 재능에 더 큰 가치가 매겨지고 자본이 모이는 파이가 확대되지 않을까? 사방팔방에서 당신의 목소리를 AI 학습데이터로 사용하고 싶다고 하는데 말이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[밑줄긋기] 기획의 인문학 ]]></title>
            <link>https://velog.io/@g_bintree/%EB%B0%91%EC%A4%84%EA%B8%8B%EA%B8%B0-%EA%B8%B0%ED%9A%8D%EC%9D%98-%EC%9D%B8%EB%AC%B8%ED%95%99</link>
            <guid>https://velog.io/@g_bintree/%EB%B0%91%EC%A4%84%EA%B8%8B%EA%B8%B0-%EA%B8%B0%ED%9A%8D%EC%9D%98-%EC%9D%B8%EB%AC%B8%ED%95%99</guid>
            <pubDate>Tue, 09 Jan 2024 15:39:38 GMT</pubDate>
            <description><![CDATA[<p>기획의 인문학 (저자 홍경수)</p>
<h3 id="불확실성을-견디는-참을성">불확실성을 견디는 참을성</h3>
<p>(110p)
기획의 실마리를 잡기 전에는 다양한 자극에 노출하는 등 느긋하게 힘을 빼고 이완해야 한다. 하지만 실마리가 잡힌 다음에는 집중해서 아이디어와 씨름해야 한다. 큰 아이디어는 수많은 작은 아이디어들로 구성되어 있기 때문이다. 큰 아이디어를 채워나가기 위해서는 고단한 작업의 과정이 필요하다.
뉴턴이나 아르키메데스와 케쿨레가 느긋하게 이완하면서 아이디어에 대한 힌트를 얻었다고 하지만 이들은 평소에 해답을 찾는 데 골몰하고 있었음이 틀림없다.</p>
<p>(112p)
...우어반의 설명에서 놀라운 점은 참을성이라는 요소가 창의력 구성요소에 포함되어 있다는 사실이었다. 내가 만났던 뛰어난 PC들에게 참을성이라는 공통적 특성이 있었다는 것도 생각났다. 창의력이란 낯설고 새로운 것을 시도하고 주변의 시선에 담담할 수 있는 용기라고도 풀어쓸 수 있다.</p>
<p>(116p)
불확실성을 견디는 참을성이라는 요소는 창의력이 반짝거리는 아이디어만으로만 만들어지지 않는다는 사실을 보여준다. 기획자는 새로운 아이디어를 냈을 때 부젼 사람들의 차가운 반응을 견뎌야 하며, 아이디어가 뿌리를 내리기까지 걸리는 시간을 이겨내야 한다. </p>
<p>&quot;작은 것부터 시작하자, 뭐라도 해보자&quot;
규모가 어떻든 목표를 달성하고자 하는 의지와 책임감</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[초경량 웹페이지 개발하기 - git repo를 DB처럼]]></title>
            <link>https://velog.io/@g_bintree/%EC%B4%88%EA%B2%BD%EB%9F%89-%EC%9B%B9%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%B0-git-repo%EB%A5%BC-DB%EC%B2%98%EB%9F%BC</link>
            <guid>https://velog.io/@g_bintree/%EC%B4%88%EA%B2%BD%EB%9F%89-%EC%9B%B9%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%B0-git-repo%EB%A5%BC-DB%EC%B2%98%EB%9F%BC</guid>
            <pubDate>Mon, 30 Oct 2023 15:08:39 GMT</pubDate>
            <description><![CDATA[<h2 id="소스코드">소스코드</h2>
<p><a href="https://github.com/Gbintree/DevForDuck-LUCY/tree/main">https://github.com/Gbintree/DevForDuck-LUCY/tree/main</a></p>
<ul>
<li><code>youtube_api_module.py</code> : video 리스트 요청 &amp; csv 저장</li>
<li><code>index.html</code> : github.io 페이지 GUI 와 csv 파일 데이터 연동</li>
</ul>
<h2 id="step-1">Step 1</h2>
<p>Youtube API 로 video id, title, url, thumbnail image url 을 요청한다.</p>
<pre><code class="language-python">from googleapiclient.discovery import build

# YouTube API 키 설정
API_KEY = input(&quot;Enter your YouTube API key: &quot;)

# YouTube API 클라이언트 생성
youtube = build(&#39;youtube&#39;, &#39;v3&#39;, developerKey=API_KEY)</code></pre>
<pre><code class="language-python">search_keyword = input(&quot;Enter Search Keyword: &quot;)
max_results = 10

search_response = youtube.search().list(
    q=search_keyword,
    type=&#39;video&#39;,
    part=&#39;id,snippet&#39;,
    maxResults=max_results,
    order=&#39;viewCount&#39;
).execute()

videos = []
for search_result in search_response.get(&#39;items&#39;, []):
    video_id = search_result[&#39;id&#39;][&#39;videoId&#39;]
    video_title = search_result[&#39;snippet&#39;][&#39;title&#39;]
    video_url = f&#39;https://www.youtube.com/watch?v={video_id}&#39;
    thumbnail_url = search_result[&#39;snippet&#39;][&#39;thumbnails&#39;][&#39;high&#39;][&#39;url&#39;]

    videos.append([video_id,video_title, video_url, thumbnail_url])</code></pre>
<h2 id="step-2">Step 2</h2>
<p>결과 리스트를 csv 파일로 저장한다.</p>
<pre><code class="language-python">with open(&#39;Resources/videos.csv&#39;, &#39;w&#39;,encoding=&#39;utf-8&#39;, newline=&#39;&#39;) as csvfile:
  csv_writer = csv.writer(csvfile) # (csvfile,quoting=csv.QUOTE_NONE, escapechar=&#39;\\&#39;)
  csv_writer.writerow([&#39;Video ID&#39;,&#39;Title&#39;, &#39;URL&#39;, &#39;Thumbnail URL&#39;])
  csv_writer.writerows(videos)</code></pre>
<h2 id="step-3">Step 3</h2>
<p>csv 파일을 git repo에 업로드 후 GitHub에서 제공하는 REST API  기능을 활용하여 DB처럼 접근한다.</p>
<p>공식 문서 : <a href="https://docs.github.com/ko/rest/repos/contents?apiVersion=2022-11-28#get-repository-content">Get repository content</a></p>
<p><code>GET /repos/{owner}/{repo}/contents/{path}</code></p>
<p>javascript에서 URL로 호출하는 방법
<code>https://raw.githubusercontent.com/{owner}/{repo}/{branch}{path}</code></p>
<pre><code class="language-java">// CSV 파일 URL
const csvFileURL = &#39;https://raw.githubusercontent.com/Gbintree/DevForDuck-LUCY/main/Resources/videos.csv&#39;;

fetch(csvFileURL)
    .then(response =&gt; response.text())
    .then(data =&gt; {
        const lines = data.split(&#39;\n&#39;);

        for (let i = 1; i &lt; lines.length; i++) {
              const cells = lines[i].split(/,(?=(?:(?:[^&quot;]*&quot;){2})*[^&quot;]*$)/); 
                  if (cells.length === 4) {
                      const [video_id,title, url, thumbnail] = cells;

                      // GUI 요소와 video_id, title, url, thumbnail 연동
                   }
    })</code></pre>
<h2 id="결과물">결과물</h2>
<p>셀프 개발한 덕질용 페이지 링크
<a href="https://gbintree.github.io/DevForDuck-LUCY/">https://gbintree.github.io/DevForDuck-LUCY/</a></p>
<p>참고
<a href="https://computer-science-student.tistory.com/297">https://computer-science-student.tistory.com/297</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Colab에서 RVC 학습된 모델로 Convert 하기]]></title>
            <link>https://velog.io/@g_bintree/Colab%EC%97%90%EC%84%9C-RVC-%ED%95%99%EC%8A%B5%EB%90%9C-%EB%AA%A8%EB%8D%B8%EB%A1%9C-Convert-%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@g_bintree/Colab%EC%97%90%EC%84%9C-RVC-%ED%95%99%EC%8A%B5%EB%90%9C-%EB%AA%A8%EB%8D%B8%EB%A1%9C-Convert-%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 20 Sep 2023 14:46:03 GMT</pubDate>
            <description><![CDATA[<h2 id="모듈-import">모듈 import</h2>
<pre><code class="language-python">from infer.modules.vc.modules import VC</code></pre>
<h2 id="변환할-오디오-추가">변환할 오디오 추가</h2>
<p><img src="https://velog.velcdn.com/images/g_bintree/post/0dc1a91c-7ad8-4e32-9211-295b8c59c516/image.png" alt=""></p>
<h2 id="pth와-index-의-집파일-다운로드">.pth와 .index 의 집파일 다운로드</h2>
<pre><code class="language-python"> import subprocess
 zipfile_path = &#39;./zips/&#39; + &quot;MODELNAME&quot;
 url = 구글드라이브 공유 URL
 subprocess.run([&quot;gdown&quot;, url, &quot;--fuzzy&quot;, &quot;-O&quot;, zipfile_path])</code></pre>
<h2 id="변환">변환</h2>
<pre><code class="language-py">def vc_single(
        self, # 디폴트 0 
        sid,  # ??
        input_audio_path,# 처리할 오디오 폴더의 경로
        f0_up_key, # 키 올림 내림. int. 12 -&gt; 1옥타브
        f0_file, # 피치 관련인듯. 걍 디폴트 0
        f0_method, #  &quot;pm&quot;, &quot;harvest&quot;, &quot;crepe&quot;, &quot;rmvpe&quot; 중 하나
        file_index, # &quot;&quot;
        file_index2, # .index 파일 경로
        index_rate, # 뭔진 모르겠으나 0.66 디폴트
        filter_radius, # 뭔진 모르겠으나 3 디폴트
        resample_sr, # 뭔진 모르겠으나 0 디폴트
        rms_mix_rate, # 뭔진 모르겠으나 0.21 디폴트
        protect, # 뭔진 모르겠으나 0.33 디폴트
    ) </code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Colab에서 RVC 모델로 Train 하기 ]]></title>
            <link>https://velog.io/@g_bintree/Colab%EC%97%90%EC%84%9C-RVC-%EB%AA%A8%EB%8D%B8%EB%A1%9C-Train-%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@g_bintree/Colab%EC%97%90%EC%84%9C-RVC-%EB%AA%A8%EB%8D%B8%EB%A1%9C-Train-%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 20 Sep 2023 12:40:37 GMT</pubDate>
            <description><![CDATA[<h2 id="intro">Intro</h2>
<p>Google Colab에서 무료 이용자에게 gradio UI 사용을 내용으로 새로운 제한사항을 추가하였다. 따라서 Easy GUI 또한 이에 영향을 받아 유료 사용자가 아닌 이상 graio UI 기반으로 사용할 수 없게 되었다. 이 변동사항에 대응하여 colab에서 수동으로 코드를 직접 실행할 수 있게끔 하는 노트북을 추가하였다.</p>
<p>처음에는 당황했는데 오히려 UI 뒤에 가려져있던 전체 코드가 깔끔한 형식으로 공개되어 RVC 모델 공부에 도움이 되었다. </p>
<p>기존 EasyGUI 
<a href="https://colab.research.google.com/drive/1r4IRL0UA7JEoZ0ZK8PKfMyTIBHKpyhcw#scrollTo=FFfC9x239kC1">https://colab.research.google.com/drive/1r4IRL0UA7JEoZ0ZK8PKfMyTIBHKpyhcw#scrollTo=FFfC9x239kC1</a></p>
<p>Colab 기반으로 RVC 실행할 수 있게 해놓은 또다른 기여자</p>
<p><a href="https://github.com/ardha27/AI-Song-Cover-RVC">https://github.com/ardha27/AI-Song-Cover-RVC</a></p>
<h2 id="00setup">00.Setup</h2>
<ul>
<li>drive.mount는 찝찝하므로 주석처리하고 
<code>if not os.path.exists(&#39;/content/drive&#39;):
  print(&quot;Your drive is not mounted. Creating Fake Drive.&quot;)</code>
조건문 타고 들어가도록 처리</li>
<li>온갖 설치가 이뤄지는 단계. 엄청나게 긴 로그가 3분가량 줄줄 출력되다가 Success 버튼이 뿅 나타난다.<pre><code>%cd /content
#from google.colab import drive
#drive.mount(&#39;/content/drive&#39;)
from IPython.display import clear_output
from ipywidgets import Button
import os
if not os.path.exists(&#39;/content/drive&#39;):
  print(&quot;Your drive is not mounted. Creating Fake Drive.&quot;)
  os.makedirs(&#39;/content/drive/MyDrive&#39;)
if not os.path.exists(&#39;/content/drive/MyDrive/project-main&#39;):
  !wget https://huggingface.co/Rejekts/project/resolve/main/project-main.zip -O &#39;/content/project-main.zip&#39; &amp;&amp; unzip &#39;project-main.zip&#39; -d /content/drive/MyDrive
!cd &#39;/content/drive/MyDrive/project-main&#39; &amp;&amp; python download_files.py &amp;&amp; pip install -r &#39;requirements-safe.txt&#39;
!rm /content/project-main.zip
!rm -r /content/sample_data
!mkdir -p /content/dataset
clear_output()
Button(description=&quot;\u2714 Success&quot;, button_style=&quot;success&quot;)</code></pre></li>
</ul>
<h2 id="01preprocess-data">01.Preprocess Data</h2>
<ul>
<li>model_name 입력해준다</li>
<li>/content/dataset/ 에 학습용 데이터 업로드한다</li>
<li><code>/content/drive/MyDrive/project-main
Starting...</code> 로그 한줄 뜨고 동일하게 Success 버튼 뿅 나타난다<pre><code>%cd /content/drive/MyDrive/project-main
model_name = &#39;My-Voice&#39; #@param {type:&quot;string&quot;}
#@markdown &lt;small&gt; Enter the path to your dataset, or if you want just upload the audios using the File Manager into the &#39;dataset&#39; folder.
dataset_folder = &#39;/content/dataset&#39; #@param {type:&quot;string&quot;}
while len(os.listdir(dataset_folder)) &lt; 1:
  input(&quot;Your dataset folder is empty.&quot;)
!mkdir -p ./logs/{model_name}
with open(f&#39;./logs/{model_name}/preprocess.log&#39;,&#39;w&#39;) as f:
  print(&quot;Starting...&quot;)
!python infer/modules/train/preprocess.py {dataset_folder} 40000 2 ./logs/{model_name} False 3.0 &gt; /dev/null 2&gt;&amp;1
with open(f&#39;./logs/{model_name}/preprocess.log&#39;,&#39;r&#39;) as f:
  if &#39;end preprocess&#39; in f.read():
      clear_output()
      display(Button(description=&quot;\u2714 Success&quot;, button_style=&quot;success&quot;))
  else:
      print(&quot;Error preprocessing data... Make sure your dataset folder is correct.&quot;)
</code></pre></li>
</ul>
<pre><code>
## 2.Extract Features
- `&quot;pm&quot;, &quot;harvest&quot;, &quot;rmvpe&quot;, &quot;rmvpe_gpu&quot;`  중에서 하나 선택
- 동일하게 Success 버튼 뿅 나타난다</code></pre><p>f0method = &quot;rmvpe_gpu&quot; # @param [&quot;pm&quot;, &quot;harvest&quot;, &quot;rmvpe&quot;, &quot;rmvpe_gpu&quot;]
%cd /content/drive/MyDrive/project-main
with open(f&#39;./logs/{model_name}/extract_f0_feature.log&#39;,&#39;w&#39;) as f:
    print(&quot;Starting...&quot;)
if f0method != &quot;rmvpe_gpu&quot;:
    !python infer/modules/train/extract/extract_f0_print.py ./logs/{model_name} 2 {f0method}
else:
    !python infer/modules/train/extract/extract_f0_rmvpe.py 1 0 0 ./logs/{model_name} True
!python infer/modules/train/extract_feature_print.py cuda:0 1 0 0 ./logs/{model_name} v2
with open(f&#39;./logs/{model_name}/extract_f0_feature.log&#39;,&#39;r&#39;) as f:
    if &#39;all-feature-done&#39; in f.read():
        clear_output()
        display(Button(description=&quot;\u2714 Success&quot;, button_style=&quot;success&quot;))
    else:
        print(&quot;Error preprocessing data... Make sure your data was preprocessed.&quot;)</p>
<pre><code> ## 03.Train Index
 - 동일하게 Success 버튼 뿅 나타난다</code></pre><p> import numpy as np
import faiss
%cd /content/drive/MyDrive/project-main
def train_index(exp_dir1, version19):
    exp_dir = &quot;logs/%s&quot; % (exp_dir1)
    os.makedirs(exp_dir, exist_ok=True)
    feature_dir = (
        &quot;%s/3_feature256&quot; % (exp_dir)
        if version19 == &quot;v1&quot;
        else &quot;%s/3_feature768&quot; % (exp_dir)
    )
    if not os.path.exists(feature_dir):
        return &quot;请先进行特征提取!&quot;
    listdir_res = list(os.listdir(feature_dir))
    if len(listdir_res) == 0:
        return &quot;请先进行特征提取！&quot;
    infos = []
    npys = []
    for name in sorted(listdir_res):
        phone = np.load(&quot;%s/%s&quot; % (feature_dir, name))
        npys.append(phone)
    big_npy = np.concatenate(npys, 0)
    big_npy_idx = np.arange(big_npy.shape[0])
    np.random.shuffle(big_npy_idx)
    big_npy = big_npy[big_npy_idx]
    if big_npy.shape[0] &gt; 2e5:
        infos.append(&quot;Trying doing kmeans %s shape to 10k centers.&quot; % big_npy.shape[0])
        yield &quot;\n&quot;.join(infos)
        try:
            big_npy = (
                MiniBatchKMeans(
                    n_clusters=10000,
                    verbose=True,
                    batch_size=256 * config.n_cpu,
                    compute_labels=False,
                    init=&quot;random&quot;,
                )
                .fit(big_npy)
                .cluster_centers_
            )
        except:
            info = traceback.format_exc()
            logger.info(info)
            infos.append(info)
            yield &quot;\n&quot;.join(infos)</p>
<pre><code>np.save(&quot;%s/total_fea.npy&quot; % exp_dir, big_npy)
n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)
infos.append(&quot;%s,%s&quot; % (big_npy.shape, n_ivf))
yield &quot;\n&quot;.join(infos)
index = faiss.index_factory(256 if version19 == &quot;v1&quot; else 768, &quot;IVF%s,Flat&quot; % n_ivf)
infos.append(&quot;training&quot;)
yield &quot;\n&quot;.join(infos)
index_ivf = faiss.extract_index_ivf(index)  #
index_ivf.nprobe = 1
index.train(big_npy)
faiss.write_index(
    index,
    &quot;%s/trained_IVF%s_Flat_nprobe_%s_%s_%s.index&quot;
    % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
)

infos.append(&quot;adding&quot;)
yield &quot;\n&quot;.join(infos)
batch_size_add = 8192
for i in range(0, big_npy.shape[0], batch_size_add):
    index.add(big_npy[i : i + batch_size_add])
faiss.write_index(
    index,
    &quot;%s/added_IVF%s_Flat_nprobe_%s_%s_%s.index&quot;
    % (exp_dir, n_ivf, index_ivf.nprobe, exp_dir1, version19),
)
infos.append(
    &quot;成功构建索引，added_IVF%s_Flat_nprobe_%s_%s_%s.index&quot;
    % (n_ivf, index_ivf.nprobe, exp_dir1, version19)
)</code></pre><p>training_log = train_index(model_name, &#39;v2&#39;)
for line in training_log:
    print(line)
    if &#39;adding&#39; in line:
        clear_output()
        display(Button(description=&quot;\u2714 Success&quot;, button_style=&quot;success&quot;)) ```</p>
<h2 id="04-train-model">04. Train Model</h2>
<ul>
<li>맨처음 입력했던 것과 동일한 model_name 입력</li>
<li>아래처럼 epoch 로그 출력되면 Train 시작된 것</li>
</ul>
<p><code>INFO:yuri:Train Epoch: 1 [0%]
INFO:yuri:[0, 0.0001]
INFO:yuri:loss_disc=4.686, loss_gen=2.666, loss_fm=14.291,loss_mel=40.714, loss_kl=9.000
INFO:yuri:====&gt; Epoch: 1 [2023-09-20 12:36:45] | (0:00:34.700875)
INFO:yuri:====&gt; Epoch: 2 [2023-09-20 12:36:50] | (0:00:05.268260)</code></p>
<pre><code>%cd /content/drive/MyDrive/project-main
from random import shuffle
import json
import os
import pathlib
from subprocess import Popen, PIPE, STDOUT
now_dir=os.getcwd()
#@markdown &lt;small&gt; Enter the name of your model again. It must be the same you chose before.
model_name = &#39;&#39;#@param {type:&quot;string&quot;}
#@markdown &lt;small&gt; Choose how often to save the model and how much training you want it to have.
save_frequency = 25 # @param {type:&quot;slider&quot;, min:5, max:50, step:5}
epochs = 200 # @param {type:&quot;slider&quot;, min:10, max:1000, step:10}
#@markdown &lt;small&gt; ONLY cache datasets under 10 minutes long. Otherwise leave this unchecked.
cache = False #@param {type:&quot;boolean&quot;}
# Remove the logging setup

def click_train(
    exp_dir1,
    sr2,
    if_f0_3,
    spk_id5,
    save_epoch10,
    total_epoch11,
    batch_size12,
    if_save_latest13,
    pretrained_G14,
    pretrained_D15,
    gpus16,
    if_cache_gpu17,
    if_save_every_weights18,
    version19,
):
    # 生成filelist
    exp_dir = &quot;%s/logs/%s&quot; % (now_dir, exp_dir1)
    os.makedirs(exp_dir, exist_ok=True)
    gt_wavs_dir = &quot;%s/0_gt_wavs&quot; % (exp_dir)
    feature_dir = (
        &quot;%s/3_feature256&quot; % (exp_dir)
        if version19 == &quot;v1&quot;
        else &quot;%s/3_feature768&quot; % (exp_dir)
    )
    if if_f0_3:
        f0_dir = &quot;%s/2a_f0&quot; % (exp_dir)
        f0nsf_dir = &quot;%s/2b-f0nsf&quot; % (exp_dir)
        names = (
            set([name.split(&quot;.&quot;)[0] for name in os.listdir(gt_wavs_dir)])
            &amp; set([name.split(&quot;.&quot;)[0] for name in os.listdir(feature_dir)])
            &amp; set([name.split(&quot;.&quot;)[0] for name in os.listdir(f0_dir)])
            &amp; set([name.split(&quot;.&quot;)[0] for name in os.listdir(f0nsf_dir)])
        )
    else:
        names = set([name.split(&quot;.&quot;)[0] for name in os.listdir(gt_wavs_dir)]) &amp; set(
            [name.split(&quot;.&quot;)[0] for name in os.listdir(feature_dir)]
        )
    opt = []
    for name in names:
        if if_f0_3:
            opt.append(
                &quot;%s/%s.wav|%s/%s.npy|%s/%s.wav.npy|%s/%s.wav.npy|%s&quot;
                % (
                    gt_wavs_dir.replace(&quot;\\&quot;, &quot;\\\\&quot;),
                    name,
                    feature_dir.replace(&quot;\\&quot;, &quot;\\\\&quot;),
                    name,
                    f0_dir.replace(&quot;\\&quot;, &quot;\\\\&quot;),
                    name,
                    f0nsf_dir.replace(&quot;\\&quot;, &quot;\\\\&quot;),
                    name,
                    spk_id5,
                )
            )
        else:
            opt.append(
                &quot;%s/%s.wav|%s/%s.npy|%s&quot;
                % (
                    gt_wavs_dir.replace(&quot;\\&quot;, &quot;\\\\&quot;),
                    name,
                    feature_dir.replace(&quot;\\&quot;, &quot;\\\\&quot;),
                    name,
                    spk_id5,
                )
            )
    fea_dim = 256 if version19 == &quot;v1&quot; else 768
    if if_f0_3:
        for _ in range(2):
            opt.append(
                &quot;%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s/logs/mute/2a_f0/mute.wav.npy|%s/logs/mute/2b-f0nsf/mute.wav.npy|%s&quot;
                % (now_dir, sr2, now_dir, fea_dim, now_dir, now_dir, spk_id5)
            )
    else:
        for _ in range(2):
            opt.append(
                &quot;%s/logs/mute/0_gt_wavs/mute%s.wav|%s/logs/mute/3_feature%s/mute.npy|%s&quot;
                % (now_dir, sr2, now_dir, fea_dim, spk_id5)
            )
    shuffle(opt)
    with open(&quot;%s/filelist.txt&quot; % exp_dir, &quot;w&quot;) as f:
        f.write(&quot;\n&quot;.join(opt))

    # Replace logger.debug, logger.info with print statements
    print(&quot;Write filelist done&quot;)
    print(&quot;Use gpus:&quot;, str(gpus16))
    if pretrained_G14 == &quot;&quot;:
        print(&quot;No pretrained Generator&quot;)
    if pretrained_D15 == &quot;&quot;:
        print(&quot;No pretrained Discriminator&quot;)
    if version19 == &quot;v1&quot; or sr2 == &quot;40k&quot;:
        config_path = &quot;configs/v1/%s.json&quot; % sr2
    else:
        config_path = &quot;configs/v2/%s.json&quot; % sr2
    config_save_path = os.path.join(exp_dir, &quot;config.json&quot;)
    if not pathlib.Path(config_save_path).exists():
        with open(config_save_path, &quot;w&quot;, encoding=&quot;utf-8&quot;) as f:
            with open(config_path, &quot;r&quot;) as config_file:
                config_data = json.load(config_file)
                json.dump(
                    config_data,
                    f,
                    ensure_ascii=False,
                    indent=4,
                    sort_keys=True,
                )
            f.write(&quot;\n&quot;)

    cmd = (
        &#39;python infer/modules/train/train.py -e &quot;%s&quot; -sr %s -f0 %s -bs %s -g %s -te %s -se %s %s %s -l %s -c %s -sw %s -v %s&#39;
        % (
            exp_dir1,
            sr2,
            1 if if_f0_3 else 0,
            batch_size12,
            gpus16,
            total_epoch11,
            save_epoch10,
            &quot;-pg %s&quot; % pretrained_G14 if pretrained_G14 != &quot;&quot; else &quot;&quot;,
            &quot;-pd %s&quot; % pretrained_D15 if pretrained_D15 != &quot;&quot; else &quot;&quot;,
            1 if if_save_latest13 == True else 0,
            1 if if_cache_gpu17 == True else 0,
            1 if if_save_every_weights18 == True else 0,
            version19,
        )
    )
    # Use PIPE to capture the output and error streams
    p = Popen(cmd, shell=True, cwd=now_dir, stdout=PIPE, stderr=STDOUT, bufsize=1, universal_newlines=True)

    # Print the command&#39;s output as it runs
    for line in p.stdout:
        print(line.strip())

    # Wait for the process to finish
    p.wait()
    return &quot;训练结束, 您可查看控制台训练日志或实验文件夹下的train.log&quot;
%load_ext tensorboard
%tensorboard --logdir ./logs
training_log = click_train(
    model_name,
    &#39;40k&#39;,
    True,
    0,
    save_frequency,
    epochs,
    7,
    True,
    &#39;assets/pretrained_v2/f0G40k.pth&#39;,
    &#39;assets/pretrained_v2/f0D40k.pth&#39;,
    0,
    cache,
    True,
    &#39;v2&#39;,
)
print(training_log)</code></pre><h2 id="train-진행-로그">Train 진행 로그</h2>
<p>  정상적으로 진행중</p>
<p>  epoch 100 번째
  <code>INFO:yuri:loss_disc=3.579, loss_gen=3.896, loss_fm=14.513,loss_mel=21.135, loss_kl=0.846</code>
  <img src="https://velog.velcdn.com/images/g_bintree/post/f3fe15ce-fb89-4fbf-8522-a17063d4f496/image.png" alt=""></p>
<p>  epoch 230번째. 학습 종료
  <img src="https://velog.velcdn.com/images/g_bintree/post/5274124e-559d-4235-b5af-9fdf35afe0e4/image.png" alt=""></p>
<p>  .pth 파일와 .index 파일 생성
  <img src="https://velog.velcdn.com/images/g_bintree/post/409f2507-7cd5-44db-a15e-e4e28fd38f43/image.png" alt="">
<img src="https://velog.velcdn.com/images/g_bintree/post/d53f559d-2dfe-4292-828a-f0bc94dec657/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[RVC 모델 (AI 커버곡 생성 모델) 과 오픈소스 커뮤니티 - 2편]]></title>
            <link>https://velog.io/@g_bintree/RVC-%EB%AA%A8%EB%8D%B8-AI-%EC%BB%A4%EB%B2%84%EA%B3%A1-%EC%83%9D%EC%84%B1-%EB%AA%A8%EB%8D%B8-%EA%B3%BC-%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-%EC%BB%A4%EB%AE%A4%EB%8B%88%ED%8B%B0-2%ED%8E%B8</link>
            <guid>https://velog.io/@g_bintree/RVC-%EB%AA%A8%EB%8D%B8-AI-%EC%BB%A4%EB%B2%84%EA%B3%A1-%EC%83%9D%EC%84%B1-%EB%AA%A8%EB%8D%B8-%EA%B3%BC-%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-%EC%BB%A4%EB%AE%A4%EB%8B%88%ED%8B%B0-2%ED%8E%B8</guid>
            <pubDate>Wed, 13 Sep 2023 16:31:27 GMT</pubDate>
            <description><![CDATA[<h1 id="intro">Intro</h1>
<p>1편 포스트에서 소개했던 <a href="https://colab.research.google.com/drive/1r4IRL0UA7JEoZ0ZK8PKfMyTIBHKpyhcw#scrollTo=Sb5fzhzEXK8X">Easy GUI</a> 일단 저번에 찾지 못했던 개발자 repo를 발견했다.
<a href="https://github.com/luisesantillan/project">https://github.com/luisesantillan/project</a></p>
<p>23년 9월 12일 버젼으로 업데이트가 있었는데<br><a href="https://colab.research.google.com/drive/1r4IRL0UA7JEoZ0ZK8PKfMyTIBHKpyhcw#scrollTo=Sb5fzhzEXK8X">Easy GUI</a> 가 어쩌면 유료화하려고 각을 재고 있는건지도 모르겠단 생각이 든다. 그 이유는 아래와 같은데, </p>
<ul>
<li>Donation 링크가 23년 6월 24일 버젼에선 없었지만 23년 8월 18일 버젼부터 등장</li>
<li>아래처럼 UI가 확 바뀜
<img src="https://velog.velcdn.com/images/g_bintree/post/9ef93f98-e396-41d1-9b18-eab170960636/image.png" alt=""></li>
<li>사용자 급증으로 인한 트래픽 문제인지 아니면 개발자 본인이 일부러 트래픽 제한을 걸어둔건지 (<em>보통 빠른 응답을 원하면 결제하라고 유도하지 않나</em>) 는 모르겠지만 이전에는 발생하지 않던 업로드 관련과 connection 끊기는 에러가 자주 나타난다. colab 로컬 환경이라 외부 서버와 연결된게 없는 줄 알았는데 일단 gradio 자체를 잘 모르기도 하고 좀더 알아봐야 할 것 같다.</li>
<li>colab 터미널에서 출력되는 메시지가 훨씬 많아지고 실행시작까지 걸리는 시간이 길어짐</li>
<li>일단 라이센스는 아래와 같이 MIT로 원본 repo랑 동일하다.
<img src="https://velog.velcdn.com/images/g_bintree/post/5db25ef8-93b3-4162-bc0d-3e34af63713f/image.png" alt=""></li>
</ul>
<h1 id="버젼별-코드">버젼별 코드</h1>
<h3 id="23년-8월-18일-버젼">23년 8월 18일 버젼</h3>
<pre><code class="language-#@markdown">#@markdown Check to load models from your Google Drive RVC folder
import os, zipfile, shutil, tarfile
import ipywidgets as widgets
from IPython.display import clear_output
backup = {
        &#39;hubert_base.pt&#39;:&#39;https://drive.google.com/file/d/1tHNmjoSHJj7G2xX_Knz4zZ8Mg7g-VhAW/view?usp=sharing&#39;,
        &#39;pretrained_v2/D40k.pth&#39;:&#39;https://drive.google.com/file/d/1BJ3TKdn2xAK9VbV8UIDoo_9K4Yyfjs7-/view?usp=sharing -O pretrained_v2/D40k.pth&#39;,
        &#39;pretrained_v2/G40k.pth&#39;:&#39;https://drive.google.com/file/d/1BJ3TKdn2xAK9VbV8UIDoo_9K4Yyfjs7-/view?usp=sharing -O pretrained_v2/G40k.pth&#39;,
        &#39;pretrained_v2/f0D40k.pth&#39;:&#39;https://drive.google.com/file/d/1A33v5MT1L_-v4iP550ibl5givEqgDus1/view?usp=sharing -O pretrained_v2/f0D40k.pth&#39;,
        &#39;pretrained_v2/f0G40k.pth&#39;:&#39;https://drive.google.com/file/d/1mMEOosc4FO3QRhYxIhHr-GVCxF05tjwV/view?usp=sharing -O pretrained_v2/f0G40k.pth&#39;,
        &#39;rmvpe.pt&#39;:&#39;https://drive.google.com/file/d/1ABwfoHKBlUsyGIy-f_axaHM6vcXxZzQU/view?usp=drive_link&#39;
}
def aria_backup(missing_file):
  url = backup[missing_file]
  !gdown --fuzzy $url
gdrive=False#@param {type:&quot;boolean&quot;}
tensorboard=False#@param {type:&quot;boolean&quot;}
f_key = &#39;WebUI&#39;
e_key = &#39;E&#39; + &#39;V&#39; + &#39;C&#39;
success=widgets.Button(description=&quot;\u2714 Success.&quot;,disabled=True, button_style=&quot;success&quot;)
if not &quot;installed&quot; in locals():
  !wget https://github.com/777gt/{e_key}/raw/main/wav2lip-HD.tar.gz
  !wget https://github.com/777gt/{e_key}/raw/main/wav2lip-cache.tar.gz
  import tarfile, os
  with tarfile.open(&#39;/content/wav2lip-cache.tar.gz&#39;, &#39;r:gz&#39;) as tar:
    for member in tar.getmembers():
      target_path = os.path.join(&#39;/&#39;, member.name)
      try:
        tar.extract(member, &#39;/&#39;)
      except:
        pass
  with tarfile.open(&#39;/content/wav2lip-HD.tar.gz&#39;) as tar:
    tar.extractall(&#39;/content&#39;)
  if gdrive:
    from google.colab import drive
    drive.mount(&#39;/content/drive&#39;)
    if os.path.exists(&#39;/content/drive&#39;):
      !mkdir -p /content/drive/MyDrive/RVC_Packages
      if not os.path.exists(&#39;/content/drive/MyDrive/RVC_Packages/Packages.tar.gz&#39;):
        !wget https://github.com/777gt/{e_key}/raw/main/Packages.tar.gz -O /content/drive/MyDrive/RVC_Packages/Packages.tar.gz
      with tarfile.open(&#39;/content/drive/MyDrive/RVC_Packages/Packages.tar.gz&#39;, &#39;r:gz&#39;) as tar:
        for member in tar.getmembers():
          target_path = os.path.join(&#39;/&#39;, member.name)
          tar.extract(member, &#39;/&#39;)
    else:
      !wget https://github.com/777gt/{e_key}/raw/main/Packages.tar.gz -O /content/Packages.tar.gz
      with tarfile.open(&#39;/content/Packages.tar.gz&#39;, &#39;r:gz&#39;) as tar:
        for member in tar.getmembers():
          target_path = os.path.join(&#39;/&#39;, member.name)
          tar.extract(member, &#39;/&#39;)
  else:
    !wget https://github.com/777gt/{e_key}/raw/main/Packages.tar.gz -O /content/Packages.tar.gz
    with tarfile.open(&#39;/content/Packages.tar.gz&#39;, &#39;r:gz&#39;) as tar:
      for member in tar.getmembers():
        target_path = os.path.join(&#39;/&#39;, member.name)
        tar.extract(member, &#39;/&#39;)
  !pip install -q gTTS torchcrepe
  !pip install gradio --upgrade
  %cd /content
  !git clone https://github.com/777gt/-EVC-
  %cd /content/-EVC-
  !wget https://huggingface.co/lj1995/VoiceConversion{f_key}/resolve/main/rmvpe.pt
  !wget https://huggingface.co/lj1995/VoiceConversion{f_key}/resolve/main/hubert_base.pt
  !wget https://huggingface.co/lj1995/VoiceConversion{f_key}/resolve/main/pretrained_v2/D40k.pth -O /content/-EVC-/pretrained_v2/D40k.pth
  !wget https://huggingface.co/lj1995/VoiceConversion{f_key}/resolve/main/pretrained_v2/G40k.pth -O /content/-EVC-/pretrained_v2/G40k.pth
  !wget https://huggingface.co/lj1995/VoiceConversion{f_key}/resolve/main/pretrained_v2/f0D40k.pth -O /content/-EVC-/pretrained_v2/f0D40k.pth
  !wget https://huggingface.co/lj1995/VoiceConversion{f_key}/resolve/main/pretrained_v2/f0G40k.pth -O /content/-EVC-/pretrained_v2/f0G40k.pth
  for file in list(backup.keys()):
    if not os.path.exists(file): aria_backup(file)
  installed=True
  clear_output()
  display(success)
if gdrive:
  if os.path.exists(&#39;/content/drive/MyDrive/RVC&#39;):
    %cd /content/drive/MyDrive/RVC
  else:
    !mkdir -p /content/drive/MyDrive/RVC
    %cd /content/drive/MyDrive/RVC
  !mkdir -p /content/unzips
  for file in os.listdir():
    if file.endswith(&#39;.zip&#39;):
      file_name=file.split(&#39;.&#39;)[0]
      zip_path = f&#39;/content/drive/MyDrive/RVC/{file}&#39;
      with zipfile.ZipFile(zip_path, &#39;r&#39;) as zip_ref:
        for member in zip_ref.infolist():
          if member.filename.endswith(&#39;.pth&#39;):
            extraction_dir=f&#39;/content/unzips/{file_name}&#39;
            file_size = member.file_size
            if file_size &lt; 100 * 1024 * 1024:
              with zip_ref.open(member) as file:
                if len(file.read()) &lt; 100 * 1024 * 1024:
                  zip_ref.extract(member, path=extraction_dir)
                  !find /content/unzips/{file_name} -name &#39;*.pth&#39; -exec mv {{}} /content/-EVC-/weights/{file_name}.pth \;
          if member.filename.endswith(&#39;.index&#39;):
            extraction_dir=f&#39;/content/unzips/&#39;
            with zip_ref.open(member) as file:
              zip_ref.extract(member, path=extraction_dir)
              !mkdir -p /content/-EVC-/logs/{file_name}
              os.chdir(f&quot;/content/-EVC-/logs/{file_name}&quot;)
              !find /content/unzips -name *.index -exec mv {} . \;
if os.path.exists(&#39;/content/unzips&#39;):
  shutil.rmtree(&#39;/content/unzips&#39;)
  pass
if tensorboard:
  %load_ext tensorboard
  %tensorboard --logdir /content/-EVC-/logs
%cd /content/-EVC-
!mkdir -p ./audios
!python3 GUI.py --colab --pycmd python3</code></pre>
<h3 id="23년-9월-12일-버젼">23년 9월 12일 버젼</h3>
<pre><code class="language-#@title">tensorboard=True#@param {type:&quot;boolean&quot;}
if not &quot;installed&quot; in locals():
    from IPython.display import clear_output
    from ipywidgets import Button
    %cd /content
    !git clone https://github.com/luisesantillan/project
    %cd /content/project
    !pip install -r requirements.txt
    !python download_files.py
    clear_output()
    Button(description=&quot;\u2714 Success&quot;, button_style=&#39;success&#39;)
    installed=True
%cd /content/project
if tensorboard:
  %load_ext tensorboard
  %tensorboard --logdir ./logs
!python app.py --colab</code></pre>
<h1 id="2편-결론">2편 결론</h1>
<p>개인적으로 해당 툴을 매우 잘 활용하고 있지만 버젼 업데이트가 되면서 여러 에러와 이슈들이 새로 생긴 부분이 아쉽다. 개인 repo에 fork 해서 디버깅이나 세부 기능을 추가하는 방식으로 기여해보고 싶다. 
다행히 나는 해당 프로젝트가 언젠가 비공개 코드로 전환되고 유료화될 수도 있다는 생각에 개인 저장소에 사본은 저장해놨다. 초반 코드부터 분석하면서 내 덕질용 니즈와 입맛에 맞게 커스터마이징 하는 것도 재밌을 것 같다. </p>
<p>코드를 보면 우선 첫번째로 눈에 띄는게 
<a href="https://github.com/777gt">https://github.com/777gt</a> 와 <a href="https://huggingface.co/lj1995">https://huggingface.co/lj1995</a> 에서 wget으로 중요해 보이는 파일을 받아온다는 것이다.</p>
<p>일단 이런 기본적인 분석부터 시작해서 커스터마이징을 시작할 수 있는 지점을 찾아야 겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[RVC 모델 (AI 커버곡 생성 모델)  과 오픈소스 커뮤니티 - 1편]]></title>
            <link>https://velog.io/@g_bintree/RVC-%EB%AA%A8%EB%8D%B8-AI-%EC%BB%A4%EB%B2%84%EA%B3%A1-%EC%83%9D%EC%84%B1-%EB%AA%A8%EB%8D%B8-%EA%B3%BC-%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-%EC%BB%A4%EB%AE%A4%EB%8B%88%ED%8B%B0-1%ED%8E%B8</link>
            <guid>https://velog.io/@g_bintree/RVC-%EB%AA%A8%EB%8D%B8-AI-%EC%BB%A4%EB%B2%84%EA%B3%A1-%EC%83%9D%EC%84%B1-%EB%AA%A8%EB%8D%B8-%EA%B3%BC-%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4-%EC%BB%A4%EB%AE%A4%EB%8B%88%ED%8B%B0-1%ED%8E%B8</guid>
            <pubDate>Sun, 10 Sep 2023 15:47:51 GMT</pubDate>
            <description><![CDATA[<h1 id="intro">Intro</h1>
<p>AI 커버곡 생성 알고리즘  RVC ( Retrieval-based-Voice-Conversion ) 을 사용하기 시작한지 한달이 되어 간다. 그동안 순수하게 덕질 목적으로 좋아하는 보컬들 AI 커버곡을 만드는데 열중했는데, 사용하다 보니 개발자 입장에서 RVC 모델 자체와 오픈소스 커뮤니티에 대해 흥미롭게 공부할 부분이 보이기 시작했다. </p>
<p>한달 간 직접 RVC 모델을 사용하며 정리한 내용을 아래와 같이 공유한다.</p>
<h1 id="rvc-오픈소스-프로젝트">RVC 오픈소스 프로젝트</h1>
<p>RVC 오픈소스 프로젝트는 아래와 같이 MIT License 정책하에 있다. 
<img src="https://velog.velcdn.com/images/g_bintree/post/b5dda468-1d2e-4500-97f1-823e272587f7/image.png" alt=""></p>
<p>덕분에 RVC 오픈소스 프로젝트에서 GUI 개선을 위한 기여가 활발히 이뤄지고 있고 훌륭한 결과물들을 누구나 공유할 수 있다. 그 중에서 아래의  <a href="https://github.com/Mangio621/Mangio-RVC-Fork">Mangio-RVC-Fork</a>가 커뮤니티 내에서 큰 주목을 받고 있다. </p>
<p><img src="https://velog.velcdn.com/images/g_bintree/post/41f64650-76db-4986-9d9f-db308af3d755/image.png" alt=""></p>
<p>그리고 이를 한차례 더 발전시켜서 Colab환경에서  <a href="https://www.gradio.app/">gradio</a> UI 기반으로 실행가능하게 개선한 <a href="https://colab.research.google.com/drive/1r4IRL0UA7JEoZ0ZK8PKfMyTIBHKpyhcw#scrollTo=Sb5fzhzEXK8X">Easy GUI</a> 가 등장했다. donation 링크에서 기여자의 개발 id가 @lesantillan 인것까진 확인했는데 git 에서 개인 repo를 아직 못 찾앗다.</p>
<p>굵직굵직한 기여 흐름을 요약하면 아래와 같다.</p>
<hr>
<p>&lt;원본 프로젝트 repo&gt; 
<a href="https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI">Retrieval-based-Voice-Conversion-WebUI
</a>↓
<a href="https://github.com/Mangio621/Mangio-RVC-Fork">Mangio-RVC-Fork</a>
↓
<a href="https://colab.research.google.com/drive/1r4IRL0UA7JEoZ0ZK8PKfMyTIBHKpyhcw#scrollTo=Sb5fzhzEXK8X">Easy GUI</a> by @lesantillan</p>
<hr>
<p>나는 @lesantillan 가 Colab에 공개한 버젼으로 RVC 모델을 학습시키고 또 해당 모델로 곡 변환하는 작업을 해왔다. 덕질한다고 나름 헤비하게 사용하고 이것저것 돌려본 경험에 기반했을 때, Colab이 무료로 기본 제공하는 GPU 리소스 할당량으로도 RVC 모델을 학습시키에 충분하다. </p>
<p>@lesantillan 가 현재진행형으로 활발히 기여하고 있는 것으로 보인다. 내가 처음 사용 시작한 버젼은 6/24/23 이고 글을 작성하는 시점에서 가장 최근 버젼은 9/08/23 이다. 그동안 새로운 버젼을 확인할 때마다 아래와 같이 개인 Colab 저장소에 복사본을 옮겨놨다.
<img src="https://velog.velcdn.com/images/g_bintree/post/c684c242-7118-4f81-af90-c848b5a940dd/image.png" alt=""></p>
<h1 id="rvc-easy-gui-실행화면">RVC Easy GUI 실행화면</h1>
<p>@lesantillan 버젼의 RVC Easy GUI를 colab에서 실행하면 아래와 같은 화면을 브라우저에서 확인할 수 있고 세개의 탭이 있다.</p>
<ol>
<li>Train
<img src="https://velog.velcdn.com/images/g_bintree/post/0a4f9a56-e830-4d8f-91c0-390ad77e985f/image.PNG" alt=""> </li>
</ol>
<ul>
<li>내가 학습시키고자 하는 가수의 목소리가 담긴 고음질 음원을 업로드하고 몇가지 설정값을 입력하면 바로 Train 이 가능하다. </li>
<li>Train이 완료되면 해당 모델을 두개의 파일 형태로 다운받을 수 있는데 각각의 파일 확장자는 <strong>.index</strong>와 <strong>.pth</strong> 이다.</li>
</ul>
<ol start="2">
<li>Download Model
<img src="https://velog.velcdn.com/images/g_bintree/post/ba634711-a07d-4908-891e-63ba5c0c8cab/image.PNG" alt=""> </li>
</ol>
<ul>
<li>1번에서 다운받은 두개의 파일을 하나의 압축파일로 만들어서 구글 드라이브에 업로드하고, 다시 해당 압축파일을 구글 드라이브로부터 colab 실행 환경에 다운로드하는 탭이다. </li>
<li>구글 드라이브에서 파일 공유용 링크를 복사해서 첫번째 텍스트 박스에 붙여넣기 한 뒤 Download 버튼을 누르면 자동으로 위 작업이 실행된다. </li>
</ul>
<ol start="3">
<li>Inference
<img src="https://velog.velcdn.com/images/g_bintree/post/55bb5562-b474-43c5-9845-5137c49197f2/image.PNG" alt=""></li>
</ol>
<ul>
<li>colab 실행 환경에 다운로드된 Trained Model에 변환하고 싶은 노래를 input으로 제공하고 이에 대한 변환 결과 파일을 생성/다운로드하는 탭이다. </li>
<li>이때 변환하고 싶은 노래는 .mp3 .wav 등의 일반 음악 파일을 업로드하면 되는데, 마이크 녹음 기능도 제공하고 있기 때문에 본인이 노래에 자신있으면 직접 부르면 된다.</li>
<li><em>실험삼아 내가 직접 노래 흥얼거리고 바로 변환을 시켜봤는데 내 최애 가수들을 음치로 만들어버리는 결과였다 ㅠ</em> </li>
</ul>
<h1 id="1편-결론">1편 결론</h1>
<p>RVC Easy GUI 버젼을 통해 누구나 비용 안들이고 AI Cover곡을 만들 수 있다.</p>
<ul>
<li>GPU 장비 하나 없어도 OK!  Colab 무료 GPU 할당량으로 모델 학습 충분</li>
<li>낮은 진입 장벽 !  코드 작업이 전혀 없기에 개발 모르는 사람들도 누구나 사용 가능</li>
<li>RVC 오픈소스 프로젝트는 MIT License 를 따른다. 현재 진행형으로 고퀄리티의 기여 결과물들이 파생되어 나오고 있다. </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[덕질만을 위한 웹페이지 개발하기 1편] #YoutubeAPI 로 직캠을 한데 모아모아]]></title>
            <link>https://velog.io/@g_bintree/%EB%8D%95%EC%A7%88%EB%A7%8C%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9B%B9%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%B0-1%ED%8E%B8-YoutubeAPI-%EB%A1%9C-%EC%A7%81%EC%BA%A0%EC%9D%84-%ED%95%9C%EB%8D%B0-%EB%AA%A8%EC%95%84%EB%AA%A8%EC%95%84</link>
            <guid>https://velog.io/@g_bintree/%EB%8D%95%EC%A7%88%EB%A7%8C%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9B%B9%ED%8E%98%EC%9D%B4%EC%A7%80-%EA%B0%9C%EB%B0%9C%ED%95%98%EA%B8%B0-1%ED%8E%B8-YoutubeAPI-%EB%A1%9C-%EC%A7%81%EC%BA%A0%EC%9D%84-%ED%95%9C%EB%8D%B0-%EB%AA%A8%EC%95%84%EB%AA%A8%EC%95%84</guid>
            <pubDate>Mon, 04 Sep 2023 13:04:07 GMT</pubDate>
            <description><![CDATA[<h1 id="00intro">00.Intro</h1>
<h3 id="✨덕후의-니즈-✨">✨덕후의 니즈 ✨</h3>
<p>✔ 콘서트를 다녀온 덕후는 고화질 근접 직캠으로 콘서트를 다시보고 싶었습니다. 
✔ 물론 Youtube 에 직접 접속해서 검색해도 되지만, 덕후의 입장에서는 썸네일들을 배치하는 UI와 알고리즘이 띄워주는 검색결과 자체가 아쉽게 느껴집니다.</p>
<h3 id="✨-셀프로-도출한-솔루션-✨">✨ 셀프로 도출한 솔루션 ✨</h3>
<p>✔ 팬들이 영혼을 갈아넣어 이쁘게 뽑은 썸네일들이  Grid에 맞춰 공백 없이 화면을 채워야 한다.
✔ 조회수가 높은 순으로 맨위에 배치되게 정렬한다.</p>
<h3 id="✨-개발-결과-미리보기-✨">✨ 개발 결과 미리보기 ✨</h3>
<p><img src="https://velog.velcdn.com/images/g_bintree/post/40c9029a-cfc9-4962-9c51-107e654f4bbe/image.png" alt=""></p>
<h1 id="01youtube-api-key-발급받기">01.Youtube API Key 발급받기</h1>
<ul>
<li>Google Cloud Platform (<a href="https://cloud.google.com">https://cloud.google.com</a>) 신규 가입자는 $300의 무료 크레딧을 받고 이를 바탕으로 전체적인 API를 3개월 간 무료 체험할 수 있다.</li>
<li>YouTube Data API v3를 사용신청을 하면 아래와 같은 페이지를 통해 Youtube API Key를 확인할 수 있다.
<img src="https://velog.velcdn.com/images/g_bintree/post/0b87ad9d-7d0e-42e9-b3c2-c3722c2d9d63/image.png" alt=""></li>
<li>$300의 무료 크레딧 정책 하에 부여받은 API 사용 할당량 또한 확인할 수 있다. ( <a href="https://developers.google.com/youtube/v3/determine_quota_cost">할당량 계산 페이지</a> ) 
<img src="https://velog.velcdn.com/images/g_bintree/post/41b05e14-7a2b-4dd7-b1a2-1d58c218a650/image.png" alt=""></li>
</ul>
<h1 id="02youtube-api-로-동영상-리스트-받아오기">02.Youtube API 로 동영상 리스트 받아오기</h1>
<p><code>youtube.search().list</code> (<a href="https://developers.google.com/youtube/v3/docs/search/list?hl=ko">공식 다큐먼트</a>)</p>
<p>아래와 같이 매개변수 쿼리를 적용하여 키워드에 맞는 동영상 리스트를 받아오고 원하는 기준으로 정렬할 수 있다.</p>
<pre><code>search_response = youtube.search().list(
        q=search_keyword,
        type=&#39;video&#39;,
        part=&#39;id,snippet&#39;,
        maxResults=max_results,
        order=&#39;viewCount&#39;  # 조회수 높은 순으로 정렬
    ).execute()</code></pre><h1 id="03썸네일-배치-ui">03.썸네일 배치 UI</h1>
<p>ver 1 ) 
챗 GPT에 <code>웹 브라우저에 썸네일들을 배치하는 UI 만들어달라</code> 라고 대충 요청해보았다.
<img src="https://velog.velcdn.com/images/g_bintree/post/fc1d6f83-375c-4d75-bc27-c1374c6ecf5e/image.png" alt=""></p>
<p>ver 2)
챗 GPT에게 <code>UI를 좀더 세련되게 만들어줘</code> 라고 요청했다.
개떡같이 모호하게 &#39;세련되게&#39; 라는 조건을 요구했는데 이걸 또 찰떡같이 알아들어서 UI를 이쁘게 다듬어 줬다.</p>
<p><img src="https://velog.velcdn.com/images/g_bintree/post/b4098287-dc57-4ce3-8591-730ac1019eb1/image.png" alt=""></p>
<p>ver 3)
내가 궁극적으로 원하던 느낌은 넷플릭스 UI 이다. 그래서 냅다 <code>넷플릭스 UI 알지? 그 느낌나게 UI 개선해줘</code> 라고 챗 GPT에게 요청했다. 근데 그걸 또 해냈다.
<img src="https://velog.velcdn.com/images/g_bintree/post/9471fe61-e3f3-49ae-9fac-a1dbda67ab43/image.png" alt=""></p>
<h1 id="04-다음에-추가하고-싶은-기능">04. 다음에 추가하고 싶은 기능</h1>
<ul>
<li>넷플릭스에서 영화 썸네일을 클릭하면 썸네일 카드가 확대되고 그 옆에 영화 소개 글이 주저리 주저리 뜬다. 이런 느낌으로 썸네일 클릭시 좋아요 수가 가장 많은 댓글 3~5개 정도를 불러와 확대된 썸네일 카드 우측에 배열되게 하고 싶다.</li>
<li>덕질의 효율성을 극대로 올리기 위해 &#39;가장 많이 다시 본 구간&#39; 으로 바로가기 할 수 있는 버튼을 만들고 싶다. 될까 싶지만 일단 API는 찾아 보기로.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[RVC 모델 Easy GUI]]></title>
            <link>https://velog.io/@g_bintree/RVC-%EB%AA%A8%EB%8D%B8-Easy-GUI</link>
            <guid>https://velog.io/@g_bintree/RVC-%EB%AA%A8%EB%8D%B8-Easy-GUI</guid>
            <pubDate>Sat, 26 Aug 2023 15:42:29 GMT</pubDate>
            <description><![CDATA[<p>GPU 장비 하나 없이 구글 colab에서 AI 모델을 학습시키는 방법</p>
<p>아래 colab 프로젝트로 이동
<a href="https://colab.research.google.com/drive/1r4IRL0UA7JEoZ0ZK8PKfMyTIBHKpyhcw#scrollTo=Sb5fzhzEXK8X">https://colab.research.google.com/drive/1r4IRL0UA7JEoZ0ZK8PKfMyTIBHKpyhcw#scrollTo=Sb5fzhzEXK8X</a></p>
<p>코드실행하면 url이 생성되고 브라우저에서 열면 된다.</p>
<p>기본 UI가 <a href="https://www.gradio.app/">gradio</a> 기반이다. 학습에 쓰일 음성파일을 업로드하거나 학습이 마무리된 모델을 로컬로 다운받는 등의 작업을 간단한 UI를 통해 손쉽게 할 수 있다.</p>
<p>코딩을 아예 모르는 사람도 다른 동영상 가이드 등을 따라하기만 하면 원하는 결과물을 낼 수 있다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[OpenAI의 DALL E 첫 사용기]]></title>
            <link>https://velog.io/@g_bintree/OpenAI%EC%9D%98-DALL-E-%EC%B2%AB-%EC%82%AC%EC%9A%A9%EA%B8%B0</link>
            <guid>https://velog.io/@g_bintree/OpenAI%EC%9D%98-DALL-E-%EC%B2%AB-%EC%82%AC%EC%9A%A9%EA%B8%B0</guid>
            <pubDate>Tue, 22 Aug 2023 14:46:35 GMT</pubDate>
            <description><![CDATA[<p>포토샵은 커녕 그림판마저 버거운 나.
AI는 상상하는 모든 것을 현실로 만들어 줄것이라는 믿음으로 DALL E 115 credit을 내돈내산했다.</p>
<p>우선 포토샵의 기본 중의 기본 기능 - 잘라내기</p>
<ol>
<li><p>원본 사진
<img src="https://velog.velcdn.com/images/g_bintree/post/f647acf3-4aef-4902-8a65-c540954f1228/image.png" alt=""></p>
</li>
<li><p>전선과 소나무를 잘라내고 뭉게구름한 한가득 한 이미지를 위해, 우선 Erase로 해당 영역을 슥슥 밀어준다.
<img src="https://velog.velcdn.com/images/g_bintree/post/5b39bd74-dc54-4a6a-b4f4-f8b11805eb8a/image.png" alt=""></p>
</li>
</ol>
<ol start="3">
<li><p>프롬프트에 명령어 입력 
<code>Complete picture with natural cloud</code>
<img src="https://velog.velcdn.com/images/g_bintree/post/44ee512a-a2e1-4eab-8d25-cd6e0257839e/image.png" alt=""></p>
</li>
<li><p>나름 만족스러운 결과물
<img src="https://velog.velcdn.com/images/g_bintree/post/46a0d303-b9b7-4846-9998-486112322fed/image.png" alt=""></p>
</li>
</ol>
<p>한발 더 나아가서 뭔가 파스텔 톤의 반짝이는 무지개 빛이 구름 사이사이로 일렁이는 그림을 보고 싶었다. </p>
<p>그래서 아래와 같은 명령어 입력
<code>Pastel tone rainbow glowing around cloud</code></p>
<p>_그치만 이런 결과물을 기대한 건 아니야
_<img src="https://velog.velcdn.com/images/g_bintree/post/bf49ea60-a156-4985-9e3d-e4da84b564c2/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[결국 유료화된 Midjourney]]></title>
            <link>https://velog.io/@g_bintree/%EA%B2%B0%EA%B5%AD-%EC%9C%A0%EB%A3%8C%ED%99%94%EB%90%9C-Midjourney</link>
            <guid>https://velog.io/@g_bintree/%EA%B2%B0%EA%B5%AD-%EC%9C%A0%EB%A3%8C%ED%99%94%EB%90%9C-Midjourney</guid>
            <pubDate>Tue, 22 Aug 2023 14:34:36 GMT</pubDate>
            <description><![CDATA[<p>나는 포토샵을 전혀 할 줄 모른다. 그림판 사용마저 버겁다.</p>
<p>그래서 표현하고 싶은 이미지 효과를 구현하려면 다른 방법을 찾아야 했다.</p>
<p>야심차게 Midjourney  Discord에 접속해서 첫 명령어를 날렸는데..
<img src="https://velog.velcdn.com/images/g_bintree/post/9786d1ec-444e-4d54-a962-6f0b4a557398/image.jpg" alt=""></p>
<p><em>이러기 있냐..</em></p>
<p>역시 오픈소스는 사용자 풀 커지고 donation 부터 시작해서 전면 유료 서비스로 가는구나..</p>
<p>플랜 정책은 아래와 같다
<img src="https://velog.velcdn.com/images/g_bintree/post/6f6995a2-53ac-4518-bb74-7113e39008c0/image.png" alt=""></p>
<h4 id=""></h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[MindsDB - Introduction]]></title>
            <link>https://velog.io/@g_bintree/MindsDB-Introduction</link>
            <guid>https://velog.io/@g_bintree/MindsDB-Introduction</guid>
            <pubDate>Tue, 15 Aug 2023 13:24:52 GMT</pubDate>
            <description><![CDATA[<p><a href="https://docs.mindsdb.com/what-is-mindsdb">공식 Document</a></p>
<p><img src="https://velog.velcdn.com/images/g_bintree/post/07063ee6-9df3-47fe-98c3-455a56f57136/image.png" alt=""></p>
<h2 id="generative-ai-tables">Generative AI Tables</h2>
<p> 생성형 AI란 기존 데이터의 패턴을 학습함으로써 텍스트, 사진 등의 새로운 내용을 생성하는 AI를 뜻한다. MindsDB는 이를 확장하여 생성형 AI 테이블 개념을 도입한다. 
 궁극적으로, 간단한 SQL 문법으로 생성형 AI에 응답을 요청하고 응답내용을 받아와 DB에 저장할 수 있다는 개념이다. </p>
<p>샘플코드 - AI Table 쿼리</p>
<pre><code>
SELECT 
  response   -- AI generated output 
FROM 
  ai_response_model  -- A generative AI model as a virtual table
WHERE 
  customer_message = &quot;Dear Team, I spilled water on the computer I bought on June 1st 2024, order #3418276, and it is no longer working, what should I do?&quot;</code></pre><p> <code>WHERE</code> 문에 챗 GPT 프롬프트 사용하는 방식과 유사하게 질문을 서술하면 된다.  </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[오픈소스로 미래를 연마하라]]></title>
            <link>https://velog.io/@g_bintree/%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4%EB%A1%9C-%EB%AF%B8%EB%9E%98%EB%A5%BC-%EC%97%B0%EB%A7%88%ED%95%98%EB%9D%BC</link>
            <guid>https://velog.io/@g_bintree/%EC%98%A4%ED%94%88%EC%86%8C%EC%8A%A4%EB%A1%9C-%EB%AF%B8%EB%9E%98%EB%A5%BC-%EC%97%B0%EB%A7%88%ED%95%98%EB%9D%BC</guid>
            <pubDate>Tue, 11 Jul 2023 15:41:00 GMT</pubDate>
            <description><![CDATA[<h1 id="foss-free-and-open-source-software">FOSS (Free and Open Source Software)</h1>
<ul>
<li>FOSSsms 소프트웨어 이상이다. 각 프로젝트는 사람들이 사람들을 위해 만든다. 사람들이 프로젝트를 사용하고 프로젝트에 기여하고 프로젝트를 후원한다. </li>
</ul>
<h1 id="자유소프트웨어의-기원">자유소프트웨어의 기원</h1>
<ul>
<li>하드웨어 중심 -&gt; 소프트웨어 중심으로 이행</li>
<li>1983년 GNU프로젝트의 시작. 완전히 자유롭게 사용하고 수정하고 배포할 수 있는 컴포넌트로 구축된 유닉스 호환 운영체제 개발을 목표로 함.</li>
<li>1985년 GNU선언문</li>
<li><blockquote>
<p>프로그램을 어떠한 목적을 위해서라도 실행할 수 있는 자유</p>
</blockquote>
</li>
<li><blockquote>
<p>소프트웨어 소스 코드를 공부하고 이를 자신의 필요에 맞게 변경할 수 있는 자유</p>
</blockquote>
</li>
<li><blockquote>
<p>소프트웨어를 복사하고 배포할 수 있는 자유</p>
</blockquote>
</li>
<li><blockquote>
<p>소프트웨어를 개선하고 이를 공유할 수 있는 자유</p>
</blockquote>
</li>
</ul>
<h1 id="오픈소스의-기원">오픈소스의 기원</h1>
<ul>
<li>자유 소프트웨어 지지자들이 오픈 방식 소프트웨어 개발의 범위와 기여자 확대를 바라며 자유소프트웨어 운동을 좀 더 기업 입맛에 맞게 만드는 방법 고안 -&gt; 오픈소스라는 용어를 새로 고안함</li>
<li>OSI 창립</li>
<li>소스를 공개하면 사유(소스가 감춰진) 소프트웨어로는 불가능한 수준의 혁신이 가능하다고 신념</li>
</ul>
<h1 id="라이센스">라이센스</h1>
<ul>
<li>라이센스 파일이 없는 코드와 프로젝트는 누구나 사용할 수 있게 기증되더라도 오픈소스가 아니다. </li>
<li>어떤 프로젝트가 오픈소스라고 스스로 주장하는데 OSI승인 라이센스로 출시되지 않는다면 그 프로젝트는 오픈소스라고 부를 수 없다.</li>
<li>저작권법과 제도를 이용하면 꼼꼼한 라이센스를 통해 소프트웨어가 늘 자유롭게 남아 있을 수 있다는 믿음</li>
<li>저작권 소유자로서 저작권을 부여받으면 그 저작물의 사용법을 제어할 권리가 생긴다. </li>
<li>제어권은 저작물 라이센스를 통해 행사할 수 있다.</li>
<li>라이센스는 사람이나 법인에게 저작권이 있는 자료를 사용할 수 있도록 허가해주는 데 쓰이는 법률 문서다.</li>
<li>“All Right Reserved” 문구가 있다면, 다른사람이 자신의 저작물을 재사용하거나 개작할 수 없다는 의미. 오직 창작자만 재사용 또는 개작 권리를 보유함</li>
<li>어떤 프로젝트가 오픈소스가 되려면 LICENSE 파일을 통해서만 가능. 해당 파일에 그 프로젝트를 접적으로 사용, 수정, 배포할 수 있다고 명시해야 한다. </li>
</ul>
<h1 id="라이센스-종류">라이센스 종류</h1>
<h2 id="카피-레프트-copyleft">카피 레프트 (copyleft)</h2>
<ul>
<li>copyright 의 언어유희..</li>
<li>사용자에게 본래 보장된 권리와 자유를 어떤 식으로든 없애거나 약화시키는 또 다른 라이센스로 공개되지 않도록 한다.</li>
<li>한번 자유로운 저작물은 영원히 자유롭게 남을 수 있다.</li>
<li>파생 저작물은 카피레프트 라이센스 저작물과 같은 조건과 조항으로 공개되어야 한다.</li>
<li>호혜성 : 당신의 창작물이 카피레프트 라이센의 저작물의 혜택을 받았다면 당신의 창작물을 사용하는 누군가도 같은 혜택을 받아야 한다.</li>
<li>대표 : GPL라이센스, LGPL, Mozilla Public License<h2 id="방임형-permissive">방임형 (permissive)</h2>
</li>
<li>소프트웨어를 변경해 재배포하는 사람은 조건과 조항을 바꿔서 새로운 배포본을 사용하는 사람에게 제공할 수 있다.</li>
<li>개발자는 파생 저작물의 라이센스를 원 저작물과 다르게 할 수 있다.</li>
<li>공개된 저작물을 사유저작물로도 활용할 수 있다.</li>
<li>대표 : 아파치 라이센스, MIT 라이센스</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[본인이 뭘하고 있는지 아는 프로그래머인가?]]></title>
            <link>https://velog.io/@g_bintree/%EB%B3%B8%EC%9D%B8%EC%9D%B4-%EB%AD%98%ED%95%98%EA%B3%A0-%EC%9E%88%EB%8A%94%EC%A7%80-%EC%95%84%EB%8A%94-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@g_bintree/%EB%B3%B8%EC%9D%B8%EC%9D%B4-%EB%AD%98%ED%95%98%EA%B3%A0-%EC%9E%88%EB%8A%94%EC%A7%80-%EC%95%84%EB%8A%94-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Sat, 08 Jul 2023 15:08:33 GMT</pubDate>
            <description><![CDATA[<h1 id="심플-소프트웨어-저자-맥스-카펫-알렉산더">심플 소프트웨어 (저자: 맥스 카펫 알렉산더)</h1>
<p>본인이 무슨 일을 하고 있는지 스스로도 모르면서 개발하는 프로그래머들이 생각외로 많다. </p>
<p>&lt;자가진단 질문 리스트&gt;</p>
<ul>
<li>내 코드에 등장하는 모든 단어와 부호를 아는가</li>
<li>내가 쓰는 함수의 문서를 모두 꼼꼼히 읽고 완전히 이해했는지</li>
<li>소프트웨어 개발의 기본 원칙을 이해하고 있는가</li>
<li>각 컴퓨터 부품이 어떻게 작동하는데, 함께 어우러질 때 또 어떤 방식으로 작동하는지 이해하고 있는가 </li>
<li>컴퓨터의 역사나 미래 발전상에 대해 아는가? 내 코드가 미래에 등장할 컴퓨터에서 어떻게 작동할 지 이해하는가?</li>
<li>프로그래밍 언어의 역사에 대해 하는가.  자신이 쓰는 언어가 어떻게 진화했음 왜 현재 그런 방식으로 작동하게 되었는지 아는가</li>
<li>내가 쓰는 것과 다른 프로그래밍 언어, 방법론, 컴퓨터의 종류에 대해 아는가. 작업에 따라 실제 가장 적합한 도구가 무엇인지도 아는가 </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[MindsDB - 트위터 AI 챗봇 튜토리얼 따라하기]]></title>
            <link>https://velog.io/@g_bintree/MinsDB%EC%99%80-%ED%8A%B8%EC%9C%84%ED%84%B0-%EC%B1%97%EB%B4%87</link>
            <guid>https://velog.io/@g_bintree/MinsDB%EC%99%80-%ED%8A%B8%EC%9C%84%ED%84%B0-%EC%B1%97%EB%B4%87</guid>
            <pubDate>Fri, 07 Jul 2023 10:40:26 GMT</pubDate>
            <description><![CDATA[<p>MindsDB가 <a href="https://twitter.com/snoop_stein">@SnoopStein</a> 이란 래퍼 겸 물리학자 챗봇을 만들었다.</p>
<p><a href="https://docs.mindsdb.com/sql/tutorials/twitter-chatbot#4-writing-tweets-using-sql">공식 튜토리얼</a></p>
<hr>
<h2 id="진행사항">진행사항</h2>
<p>일단 이걸 따라하려면 선행되어야 하는 작업이 몇단계 있다.</p>
<ol>
<li>트위터 개발 계정이 필요함 </li>
<li>MindsDB 계정을 만들어야 한다.</li>
</ol>
<h3 id="트위터-개발-계정-만들기">트위터 개발 계정 만들기</h3>
<ul>
<li><a href="https://developer.twitter.com/en">https://developer.twitter.com/en</a> 에 들어가서 내가 트위터 API로 뭔 프로젝트를 할건지 적어서 제출했다. 제출하고 하루 이틀 이상 기다리면 승인 메일을 받는 걸로 알고 있는데, 난 그냥 Developer Portal에서 내가 신청한 프로젝트랑 key를 다 확인 할 수 있는 것 같다 (뭐지?)</li>
</ul>
<p>MindsDB 공식 문서에서 필요하다고 가이드한 트위터 개발 계정 key가 아래와 같이 5개인데, 내 트위터 개발 포털 대쉬보드에서 다 확인가능하다. (뭐지?)</p>
<pre><code>CREATE DATABASE my_twitter_v2
WITH
  ENGINE = &#39;twitter&#39;,
  PARAMETERS = {
   &quot;consumer_key&quot;: &quot;your twitter App API key&quot;,
   &quot;consumer_secret&quot;: &quot;your twitter App API key secret&quot;,
   &quot;bearer_token&quot;: &quot;your twitter App bearer TOKEN&quot;,
   &quot;access_token&quot;: &quot;your twitter App Access Token&quot;,
   &quot;access_token_secret&quot;: &quot;your twitter App Access Token Secret&quot;
  };</code></pre><hr>
<h3 id="mindsdb">MindsDB</h3>
<p><a href="https://cloud.mindsdb.com/editor?utm_medium=referral&amp;utm_source=devto&amp;utm_campaign=twitter-chatbot-tutorial-2023-03&amp;_gl=1*1p6kf8i*_ga*NTcyMjc1MDA5LjE2ODg3MjY0ODg.*_ga_7LGFPGV6XV*MTY5MjA5MzIzNS4xMC4xLjE2OTIwOTMzMDcuNjAuMC4w">MindsDB SQL Editor</a></p>
<h4 id="mindsdb-계정-만들기">MindsDB 계정 만들기</h4>
<p>첫번째로, MindsDB SQL Editor 로 이동한다.</p>
<ul>
<li>first name, email, 비번 입력하면 간단하게 sign up 된다. </li>
<li>나는 일단 무료 demo 버젼으로. 유료버젼은 0.7$ per hour 이다. </li>
</ul>
<p>sign up 이후 아래와 같은 인터페이스를 확인할 수 있다.
<img src="https://velog.velcdn.com/images/g_bintree/post/5151333f-c9b3-4da1-81d0-085de6209815/image.png" alt=""></p>
<h3 id="gpt-모델-생성">GPT 모델 생성</h3>
<p><strong>GPT 모델 생성하는 예제 코드</strong></p>
<pre><code class="language-CREATE">PREDICT response
USING
engine = &#39;openai&#39;,
-- api_key = &#39;your openai key&#39;, -- in MindsDB cloud accounts we provide a default key 
model_name = &#39;gpt-4&#39;, -- you can also use &#39;text-davinci-003&#39; or &#39;gpt-3.5-turbo&#39;
prompt_template = &#39;respond to {{text}} by {{author_username}}&#39;; </code></pre>
<p>각 명령어가 수행하능 기능</p>
<ul>
<li><code>CREATE MODEL mindsdb.gpt_model</code> : gpt_model 이라는 이름의 머신 러닝 모델 생성</li>
<li><code>PREDICT response</code> : 모델이 prompt에 기반하여 응답을 예측하도록 함</li>
<li><code>USING  engine = &#39;openai&#39;</code> : OpenAI 엔진을 사용하도록 함</li>
<li><code>prompt_template</code> : GPT의 응답양식 지정</li>
</ul>
<p>결과화면
<img src="https://velog.velcdn.com/images/g_bintree/post/65b5f990-43db-44c0-bacf-2da6368d5f0f/image.png" alt=""></p>
<p><strong>생성한 GPT 모델에 응답을 요청해보자</strong></p>
<ol>
<li>튜토리얼 문서와 동일한 질문 
&quot;why is gravity so different on the sun?&quot;<pre><code>SELECT response
FROM mindsdb.gpt_model
WHERE author_username = &quot;mindsdb&quot;
AND text = &quot;why is gravity so different on the sun?&quot;;
</code></pre></li>
</ol>
<pre><code>
결과화면 - 공식 튜토리얼와 동일한 결과를 확인할 수 있다.
![](https://velog.velcdn.com/images/g_bintree/post/f88cefda-8832-4d25-be78-a490696f9d51/image.png)

2. 개인 테스트용 질문들
&quot;Explain about cubic bezier curve&quot;
결과 화면
![](https://velog.velcdn.com/images/g_bintree/post/1610b3ab-d860-4d66-96aa-76f110644c99/image.png)

### 트위터 Dev Account와 연동

```CREATE DATABASE my_twitter_v2
WITH
  ENGINE = &#39;twitter&#39;,
  PARAMETERS = {
   &quot;consumer_key&quot;: &quot;your twitter App API key&quot;,
   &quot;consumer_secret&quot;: &quot;your twitter App API key secret&quot;,
   &quot;bearer_token&quot;: &quot;your twitter App bearer TOKEN&quot;,
   &quot;access_token&quot;: &quot;your twitter App Access Token&quot;,
   &quot;access_token_secret&quot;: &quot;your twitter App Access Token Secret&quot;
  };</code></pre><p><em>버그</em>
MindsDB 공식 리포의 버그 리포트<a href="https://github.com/mindsdb/mindsdb/issues/6331">링크텍스트</a> </p>
<p>Twitter의 Elevated Access 정책이 업데이트 되며 튜토리얼 문서대로 하면 아래와 같은 이슈를 만나게 된다. </p>
<pre><code>Can&#39;t connect to db: 403 Forbidden
When authenticating requests to the Twitter API v2 endpoints, you must use keys and tokens from a Twitter developer App that is attached to a Project. You can create a project via the developer portal.</code></pre><p>해당 이슈는 &quot;bearer_token&quot; 을 제거하면 해결된다는 결론과 함께 closed 상태이다. 하지만 나는 동일한 에러 메시지를 만나고 있다...
추가 문의를 위한 comment 를 남겼으니 내부 기여자들의 답변을 기다리는 수밖에.</p>
<hr>
<p>MindsDB 커뮤니티 기여 방안들 </p>
<p>Here is what you can do:</p>
<blockquote>
<p>Go ahead and try out MindsDB by following our tutorials, and in case of problems, you can always report an issue here.</p>
</blockquote>
<blockquote>
<p>Are you familiar with Python? You can then help us out in resolving open issues. At first, have a look at issues labeled with the good first issue tag, as these should be easy to start.</p>
</blockquote>
<blockquote>
<p>You can also help us with documentation and tutorials. Here is how you can contribute by writing documentation and tutorials. Don’t forget to follow the style guide.</p>
</blockquote>
<blockquote>
<p>Share with your friends and spread the word about MindsDB.</p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>