<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Clean Architecture on Nguyen Ngoc Tin</title><link>https://ngoctin.me/tags/clean-architecture/</link><description>Recent content in Clean Architecture on Nguyen Ngoc Tin</description><generator>Hugo</generator><language>en</language><managingEditor>ngoctin.work@gmail.com (Nguyen Ngoc Tin)</managingEditor><webMaster>ngoctin.work@gmail.com (Nguyen Ngoc Tin)</webMaster><lastBuildDate>Sun, 15 Mar 2026 10:00:00 +0700</lastBuildDate><atom:link href="https://ngoctin.me/tags/clean-architecture/index.xml" rel="self" type="application/rss+xml"/><item><title>Lexi: Xây dựng AI English Speaking Tutor với Serverless Architecture và Amazon Bedrock</title><link>https://ngoctin.me/posts/lexi-ai-english-tutor/</link><pubDate>Sun, 15 Mar 2026 10:00:00 +0700</pubDate><author>ngoctin.work@gmail.com (Nguyen Ngoc Tin)</author><guid>https://ngoctin.me/posts/lexi-ai-english-tutor/</guid><description>&lt;div class="youtube-embed-wrapper" data-video-id="qPlBFtEk3pM" data-speed="1.5"&gt;&#10; &lt;div class="youtube-lite-player" onclick="playYoutubeInstant(this)" role="button" tabindex="0" aria-label="Phát video YouTube Video (tốc độ 1.5x)" onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();playYoutubeInstant(this);}"&gt;&#10; &lt;picture&gt;&#10; &lt;source srcset="https://i.ytimg.com/vi_webp/qPlBFtEk3pM/maxresdefault.webp" type="image/webp"&gt;&#10; &lt;img src="https://i.ytimg.com/vi/qPlBFtEk3pM/hqdefault.jpg" alt="YouTube Video" loading="lazy" class="youtube-poster-img" onerror="this.onerror=null;this.src='https://i.ytimg.com/vi/qPlBFtEk3pM/hqdefault.jpg';"&gt;&#10; &lt;/picture&gt;&#10; &lt;button class="youtube-play-btn" type="button" aria-hidden="true" tabindex="-1"&gt;&#10; &lt;svg viewBox="0 0 68 48" width="64" height="45" class="youtube-play-svg"&gt;&#10; &lt;path class="youtube-btn-bg" d="M66.52,7.74c-0.78-2.93-2.49-5.41-5.42-6.19C55.79,.13,34,0,34,0S12.21,.13,6.9,1.55 C3.97,2.33,2.27,4.81,1.48,7.74C0.06,13.05,0,24,0,24s0.06,10.95,1.48,16.26c0.78,2.93,2.49,5.41,5.42,6.19 C12.21,47.87,34,48,34,48s21.79-0.13,27.1-1.55c2.93-0.78,4.64-3.26,5.42-6.19C67.94,34.95,68,24,68,24S67.94,13.05,66.52,7.74z" fill="#f43f5e"&gt;&lt;/path&gt;&#10; &lt;path d="M 45,24 27,14 27,34" fill="#ffffff"&gt;&lt;/path&gt;&#10; &lt;/svg&gt;&#10; &lt;/button&gt;&#10; &lt;div class="youtube-badge-speed"&gt;1.5x Speed&lt;/div&gt;&#10; &lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;script&gt;&#10;if (!window.playYoutubeInstant) {&#10; window._ytApiCallbacks = [];&#10; window._ytApiLoading = false;&#10;&#10; window.ensureYTAPILoaded = function(cb) {&#10; if (window.YT &amp;&amp; window.YT.Player) {&#10; cb();&#10; return;&#10; }&#10; window._ytApiCallbacks.push(cb);&#10; if (!window._ytApiLoading) {&#10; window._ytApiLoading = true;&#10; var tag = document.createElement('script');&#10; tag.id = 'yt-iframe-api';&#10; tag.src = 'https://www.youtube.com/iframe_api';&#10; var first = document.getElementsByTagName('script')[0];&#10; first.parentNode.insertBefore(tag, first);&#10;&#10; var prev = window.onYouTubeIframeAPIReady;&#10; window.onYouTubeIframeAPIReady = function() {&#10; if (typeof prev === 'function') prev();&#10; while (window._ytApiCallbacks.length) {&#10; var fn = window._ytApiCallbacks.shift();&#10; try { fn(); } catch (e) { console.error(e); }&#10; }&#10; };&#10; }&#10; };&#10;&#10; window.playYoutubeInstant = function(el) {&#10; var wrapper = el.closest('.youtube-embed-wrapper');&#10; if (!wrapper) return;&#10; var id = wrapper.getAttribute('data-video-id');&#10; var start = parseInt(wrapper.getAttribute('data-start'), 10) || 0;&#10; var speed = parseFloat(wrapper.getAttribute('data-speed')) || 1.5;&#10;&#10; var playerId = 'yt-player-' + Math.random().toString(36).substr(2, 9);&#10; var playerDiv = document.createElement('div');&#10; playerDiv.id = playerId;&#10; playerDiv.className = 'youtube-iframe-active';&#10;&#10; wrapper.innerHTML = '';&#10; wrapper.appendChild(playerDiv);&#10;&#10; window.ensureYTAPILoaded(function() {&#10; var speedApplied = false;&#10; new YT.Player(playerId, {&#10; videoId: id,&#10; playerVars: {&#10; autoplay: 1,&#10; playsinline: 1,&#10; rel: 0,&#10; modestbranding: 1,&#10; start: start&#10; },&#10; events: {&#10; onReady: function(event) {&#10; try {&#10; event.target.setPlaybackRate(speed);&#10; event.target.playVideo();&#10; } catch (err) {}&#10; },&#10; onStateChange: function(event) {&#10; if (!speedApplied &amp;&amp; event.data === YT.PlayerState.PLAYING) {&#10; try {&#10; event.target.setPlaybackRate(speed);&#10; speedApplied = true;&#10; } catch (err) {}&#10; }&#10; }&#10; }&#10; });&#10; });&#10; };&#10;}&#10;&lt;/script&gt;&#10;&lt;div class="admonition abstract open"&gt;&#10; &lt;div class="admonition-title"&gt;&#10; &lt;i class="icon ti ti-list-details" aria-hidden="true"&gt;&lt;/i&gt;Abstract&#10; &lt;/div&gt;&#10; &lt;div class="admonition-content"&gt;&lt;p&gt;Lexi là trợ lý AI luyện giao tiếp phản xạ tiếng Anh hai chiều qua giọng nói thời gian thực, giúp người học phát hiện lỗi phát âm, sửa ngữ pháp và cải thiện phản xạ đàm thoại theo kịch bản thực tế.&lt;/p&gt;</description></item></channel></rss>