From d799564c38b6fd931ebafbcddb742ecc60b6a32c Mon Sep 17 00:00:00 2001 From: TheTraille18 Date: Tue, 30 Jun 2026 10:07:59 -0400 Subject: [PATCH] Update for 6_26 --- public/resume/Justin_Traille.pdf | Bin 6988 -> 42345 bytes src/components/ResumePdfViewer.tsx | 135 +++++++++++++++++++++-------- src/content/appShowcases.ts | 50 +++++++---- src/content/resumeHotspots.ts | 14 +-- 4 files changed, 138 insertions(+), 61 deletions(-) diff --git a/public/resume/Justin_Traille.pdf b/public/resume/Justin_Traille.pdf index 40e05f91d682f891db037d0a1d90f68603eebe2c..23b37f73e3ae0c01d6fc48950feb9022e7100395 100644 GIT binary patch literal 42345 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 literal 6988 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 a;e1Wo_foA9C*LQMBoN{o0PsuU+y4Q;E8tQ9 diff --git a/src/components/ResumePdfViewer.tsx b/src/components/ResumePdfViewer.tsx index 5bffb06..f9fbc7c 100644 --- a/src/components/ResumePdfViewer.tsx +++ b/src/components/ResumePdfViewer.tsx @@ -107,9 +107,6 @@ function isHotspotBoundaryLine(text: string): boolean { if (normalized.includes('internal innovation initiative')) { return true; } - if (normalized.startsWith('atos client:')) { - return true; - } return isSectionHeadingLine(text) || isJobHeadingLine(text); } @@ -162,10 +159,25 @@ function getExpandedLineIndices( return indices; } -function getLineBounds( - items: PdfTextItem[], - viewport: { width: number; height: number; transform: number[]; scale: number } -) { +interface PdfViewport { + width: number; + height: number; + transform: number[]; + scale: number; +} + +interface PageRenderData { + textLayer: HTMLDivElement; + viewport: PdfViewport; + lines: LineGroup[]; +} + +interface GlobalLineRef { + pageIndex: number; + lineIndex: number; +} + +function getLineBounds(items: PdfTextItem[], viewport: PdfViewport) { let minX = Infinity; let minY = Infinity; let maxX = -Infinity; @@ -198,6 +210,78 @@ function getLineBounds( }; } +function addHotspotHitArea( + textLayer: HTMLDivElement, + hotspot: ResumeHotspot, + items: PdfTextItem[], + viewport: PageRenderData['viewport'], + onHotspotClick?: (hotspot: ResumeHotspot) => void +) { + const bounds = getLineBounds(items, viewport); + const hitArea = document.createElement('button'); + hitArea.type = 'button'; + hitArea.className = 'resume-hotspot'; + hitArea.setAttribute('aria-label', `More about ${hotspot.title}`); + hitArea.style.left = bounds.left; + hitArea.style.top = bounds.top; + hitArea.style.width = bounds.width; + hitArea.style.height = bounds.height; + hitArea.onclick = (event) => { + event.preventDefault(); + event.stopPropagation(); + onHotspotClick?.(hotspot); + }; + textLayer.appendChild(hitArea); +} + +function placeHotspotsAcrossPages( + pages: PageRenderData[], + onHotspotClick?: (hotspot: ResumeHotspot) => void +) { + const globalLines: GlobalLineRef[] = []; + const lineGroups: LineGroup[] = []; + + pages.forEach((page, pageIndex) => { + page.lines.forEach((line, lineIndex) => { + globalLines.push({ pageIndex, lineIndex }); + lineGroups.push(line); + }); + }); + + const usedHotspotIds = new Set(); + const usedGlobalIndices = new Set(); + + globalLines.forEach((_, globalIndex) => { + if (usedGlobalIndices.has(globalIndex)) return; + + const hotspot = findResumeHotspot(lineGroups[globalIndex].text); + if (!hotspot || usedHotspotIds.has(hotspot.id)) return; + + usedHotspotIds.add(hotspot.id); + const expandedIndices = getExpandedLineIndices(lineGroups, globalIndex, hotspot); + expandedIndices.forEach((index) => usedGlobalIndices.add(index)); + + const itemsByPage = new Map(); + expandedIndices.forEach((index) => { + const { pageIndex, lineIndex } = globalLines[index]; + const lineItems = pages[pageIndex].lines[lineIndex].items; + const existing = itemsByPage.get(pageIndex) ?? []; + existing.push(...lineItems); + itemsByPage.set(pageIndex, existing); + }); + + itemsByPage.forEach((items, pageIndex) => { + addHotspotHitArea( + pages[pageIndex].textLayer, + hotspot, + items, + pages[pageIndex].viewport, + onHotspotClick + ); + }); + }); +} + export default function ResumePdfViewer({ url, onError, @@ -248,6 +332,8 @@ export default function ResumePdfViewer({ containerWidth = container.clientWidth || 860; } + const pages: PageRenderData[] = []; + for (let pageNumber = 1; pageNumber <= pdf.numPages; pageNumber += 1) { if (cancelled) return; @@ -284,36 +370,8 @@ export default function ResumePdfViewer({ ); const lines = groupTextIntoLines(textItems); - const usedHotspotIds = new Set(); - const usedLineIndices = new Set(); - - lines.forEach((line, lineIndex) => { - if (usedLineIndices.has(lineIndex)) return; - - const hotspot = findResumeHotspot(line.text); - if (!hotspot || usedHotspotIds.has(hotspot.id)) return; - - usedHotspotIds.add(hotspot.id); - const expandedIndices = getExpandedLineIndices(lines, lineIndex, hotspot); - expandedIndices.forEach((index) => usedLineIndices.add(index)); - - const mergedItems = expandedIndices.flatMap((index) => lines[index].items); - const bounds = getLineBounds(mergedItems, viewport); - const hitArea = document.createElement('button'); - hitArea.type = 'button'; - hitArea.className = 'resume-hotspot'; - hitArea.setAttribute('aria-label', `More about ${hotspot.title}`); - hitArea.style.left = bounds.left; - hitArea.style.top = bounds.top; - hitArea.style.width = bounds.width; - hitArea.style.height = bounds.height; - hitArea.onclick = (event) => { - event.preventDefault(); - event.stopPropagation(); - onHotspotClickRef.current?.(hotspot); - }; - textLayer.appendChild(hitArea); - }); + + pages.push({ textLayer, viewport, lines }); pageWrap.appendChild(canvas); pageWrap.appendChild(textLayer); @@ -324,6 +382,9 @@ export default function ResumePdfViewer({ } if (!cancelled) { + placeHotspotsAcrossPages(pages, (hotspot) => { + onHotspotClickRef.current?.(hotspot); + }); setLoading(false); } } catch (err) { diff --git a/src/content/appShowcases.ts b/src/content/appShowcases.ts index 3c25a77..7f7bc41 100644 --- a/src/content/appShowcases.ts +++ b/src/content/appShowcases.ts @@ -150,36 +150,50 @@ export const appShowcases: Record = { 'Retrieval-augmented generation for querying documents and knowledge bases with AI.', githubUrl: 'https://github.com/TheTraille18/jet_rag_ai_project', summary: [ - 'RAG System will let users upload documents, embed them into a vector store, and ask natural-language questions grounded in their own data. Answers are generated by an LLM using retrieved context rather than model memory alone.', - 'The planned architecture separates ingestion (chunking, embedding, indexing) from query time (retrieval, reranking, and response generation) so the system scales as the knowledge base grows.', + 'RAG System ingests PDF documents, embeds them with Amazon Titan on AWS Bedrock, and stores chunks in a Chroma vector database. Users ask natural-language questions and receive answers grounded in retrieved transcript context via Claude on Bedrock.', + 'A LangGraph agent judges whether the RAG answer is sufficient. If the document cannot answer the question — for example, events after the report — the agent falls back to Tavily web search and synthesizes a final response from live results.', ], architectureCaption: - 'Documents are chunked and embedded at ingest time, then stored in a vector database. At query time, the user question is embedded, relevant chunks are retrieved, and an LLM generates a grounded answer from that context.', + 'At ingest time, PDFs are chunked and embedded into Chroma. At query time, the question is embedded, relevant chunks are retrieved, and Claude generates a transcript-grounded RAG answer. A LangGraph agent then routes the flow: if the answer is sufficient, it is returned; otherwise Tavily searches the web and Claude produces a final answer from those results.', diagram: { viewBox: '0 0 760 400', boxes: [ - { x: 40, y: 40, w: 160, h: 52, label: 'Documents', sublabel: 'PDF / text', fill: 'rgba(0,0,0,0.45)' }, - { x: 280, y: 40, w: 200, h: 52, label: 'Ingest pipeline', sublabel: 'Chunk + embed', fill: 'rgba(255,90,95,0.35)' }, - { x: 540, y: 40, w: 180, h: 52, label: 'Vector store', sublabel: 'Embeddings', fill: 'rgba(0,166,153,0.35)' }, - { x: 40, y: 200, w: 160, h: 52, label: 'User query', sublabel: 'Natural language', fill: 'rgba(0,0,0,0.45)' }, - { x: 280, y: 200, w: 200, h: 52, label: 'Retrieval', sublabel: 'Similarity search', fill: 'rgba(255,90,95,0.25)' }, - { x: 540, y: 200, w: 180, h: 52, label: 'LLM', sublabel: 'Grounded answer', fill: 'rgba(0,166,153,0.25)' }, + { x: 40, y: 30, w: 150, h: 52, label: 'PDF document', sublabel: 'Earnings transcript', fill: 'rgba(0,0,0,0.45)' }, + { x: 240, y: 30, w: 180, h: 52, label: 'Ingest pipeline', sublabel: 'Chunk + Titan embed', fill: 'rgba(255,90,95,0.35)' }, + { x: 470, y: 30, w: 160, h: 52, label: 'ChromaDB', sublabel: 'Vector store', fill: 'rgba(0,166,153,0.35)' }, + { x: 40, y: 130, w: 150, h: 52, label: 'User query', sublabel: 'Natural language', fill: 'rgba(0,0,0,0.45)' }, + { x: 240, y: 130, w: 180, h: 52, label: 'Retrieval', sublabel: 'Similarity search', fill: 'rgba(255,90,95,0.25)' }, + { x: 470, y: 130, w: 160, h: 52, label: 'Claude', sublabel: 'RAG answer', fill: 'rgba(0,166,153,0.25)' }, + { x: 280, y: 240, w: 200, h: 52, label: 'LangGraph agent', sublabel: 'Judge RAG answer', fill: 'rgba(255,90,95,0.35)' }, + { x: 40, y: 330, w: 180, h: 52, label: 'Transcript answer', sublabel: 'Return RAG result', fill: 'rgba(0,166,153,0.25)' }, + { x: 300, y: 330, w: 160, h: 52, label: 'Tavily', sublabel: 'Web search', fill: 'rgba(0,0,0,0.45)' }, + { x: 520, y: 330, w: 180, h: 52, label: 'Claude', sublabel: 'Final answer', fill: 'rgba(0,166,153,0.25)' }, ], arrows: [ - { x1: 200, y1: 66, x2: 278, y2: 66 }, - { x1: 480, y1: 66, x2: 538, y2: 66 }, - { x1: 200, y1: 226, x2: 278, y2: 226 }, - { x1: 480, y1: 226, x2: 538, y2: 226 }, - { x1: 630, y1: 92, x2: 630, y2: 198 }, + { x1: 190, y1: 56, x2: 238, y2: 56 }, + { x1: 420, y1: 56, x2: 468, y2: 56 }, + { x1: 190, y1: 156, x2: 238, y2: 156 }, + { x1: 420, y1: 156, x2: 468, y2: 156 }, + { x1: 550, y1: 82, x2: 550, y2: 128 }, + { x1: 380, y1: 182, x2: 380, y2: 238 }, + { x1: 320, y1: 292, x2: 130, y2: 328 }, + { x1: 440, y1: 292, x2: 378, y2: 328 }, + { x1: 460, y1: 356, x2: 518, y2: 356 }, ], - footer: 'Planned RAG pipeline — ingest, retrieve, generate', + footer: 'Hybrid RAG + agent — transcript grounding with web search fallback', }, toolsUsed: [ - { category: 'AI', tools: ['LLM', 'Embeddings', 'Vector search', 'RAG'] }, - { category: 'Backend', tools: ['Python', 'FastAPI', 'AWS Bedrock'] }, - { category: 'Data', tools: ['ChromaDB', 'S3', 'Chunking pipeline'] }, + { category: 'AI', tools: ['RAG', 'LangChain', 'LangGraph', 'Claude', 'Titan Embeddings'] }, + { category: 'Backend', tools: ['Python', 'AWS Bedrock', 'Tavily'] }, + { category: 'Data', tools: ['ChromaDB', 'PyPDF', 'Chunking pipeline'] }, ], progressUpdates: [ + { + date: 'Jun 26, 2026', + title: 'LangGraph agent + web fallback', + detail: + 'Added a LangGraph agent that judges RAG answers and falls back to Tavily web search when the transcript cannot answer. Updated README, architecture diagram, and tools to reflect the hybrid pipeline.', + }, { date: 'Jun 25, 2026', title: 'LangChain', diff --git a/src/content/resumeHotspots.ts b/src/content/resumeHotspots.ts index 266aa95..d1d6f5a 100644 --- a/src/content/resumeHotspots.ts +++ b/src/content/resumeHotspots.ts @@ -146,6 +146,8 @@ export const resumeHotspots: ResumeHotspot[] = [ skills: [ { name: '*RAG', level: 5 }, { name: '*AI Agents', level: 5 }, + { name: '*LangChain', level: 6 }, + { name: '*LangGraph', level: 6 }, { name: 'AWS Bedrock', level: 6 }, { name: '*Amazon Titan Embeddings', level: 5 }, { name: '*ChromaDB', level: 5 }, @@ -168,7 +170,7 @@ export const resumeHotspots: ResumeHotspot[] = [ }, { id: 'blackstone', - match: 'Atos Client: Blackstone', + match: 'Blackstone |', title: 'Blackstone', detail: "As a member of Blackstone's Platform Engineering team, I supported Infrastructure as Code modernization initiatives focused on HCP Terraform. My responsibilities included onboarding existing AWS infrastructure and HCP Terraform platform configurations into Infrastructure as Code by leveraging Terraform imports and developing reusable Terraform configurations for ongoing management. This included importing HCP Terraform users, teams, and platform resources into Terraform so they could be managed through Git-based workflows instead of manual configuration through the HCP Terraform UI.\n\nThe Platform Engineering team supported multiple internal accounts, each with its own HCP Terraform configuration and infrastructure requirements. To streamline onboarding, I contributed to a React-based self-service platform that allowed users to request new HCP Terraform workspaces and account configurations. Users submitted information such as workspace names, Git repository details, and account-specific configuration requirements through the portal.\n\nTo support this workflow, I developed Python-based AWS Lambda functions that integrated with the HCP Terraform API to automate workspace lifecycle management. These services provided capabilities including creating workspaces, listing available workspaces, retrieving workspace details, and deleting workspaces through automated workflows exposed by the internal platform.\n\nOnce a workspace was provisioned, I utilized standardized Terraform module templates and account-specific configuration values to deploy and manage AWS infrastructure across development, test, and production environments in a consistent and repeatable manner.\n\nI also extended Python-based integrations with Terraform and Git platforms, resolved production issues, and improved the performance of automation workflows, including reducing the execution time of a legacy process from approximately 15 minutes to 1 minute.", @@ -176,7 +178,7 @@ export const resumeHotspots: ResumeHotspot[] = [ }, { id: 'occ', - match: 'Atos Client: The Options Clearing Corporation', + match: 'The Options Clearing Corporation |', title: 'The Options Clearing Corporation (OCC)', detail: 'As a Software Engineer Consultant supporting The Options Clearing Corporation (OCC), I contributed to applications and infrastructure supporting critical financial market operations. My engagement evolved through two distinct phases, providing experience across software testing, application deployments, Kubernetes operations, and platform engineering.\n\nDuring the first phase, I worked closely with the testing team, where I was responsible for developing and maintaining automated test coverage for enterprise applications. This included creating and rewriting Java-based Cucumber test scenarios and supporting monthly application releases. I was also responsible for deploying application updates across multiple environments using Rancher, providing hands-on experience with Kubernetes-based release management.\n\nDuring the second phase, my responsibilities shifted toward DevOps and platform engineering activities. In addition to managing application deployments, I investigated and resolved production issues, analyzed application and container failures, supported Kubernetes cluster migrations, and assisted with infrastructure modernization efforts. As part of this work, I provisioned Kubernetes clusters and gained practical experience with cluster administration, application troubleshooting, Helm deployments, Rancher operations, and containerized workloads running in enterprise environments.\n\nThis engagement provided valuable experience supporting highly available systems within a regulated financial services environment while strengthening my expertise in Kubernetes operations, deployment automation, troubleshooting, and platform support.', @@ -184,7 +186,7 @@ export const resumeHotspots: ResumeHotspot[] = [ }, { id: 'capital-one', - match: 'Atos Client: Capital One', + match: 'Capital One |', title: 'Capital One', detail: 'As a Software Engineer Consultant supporting Capital One, I contributed to enterprise cloud modernization initiatives focused on AWS Aurora PostgreSQL and Infrastructure as Code. My primary responsibility was migrating multiple application platforms from a legacy internal Infrastructure as Code framework to a newer company-standard platform designed to support Aurora PostgreSQL deployments. The migration effort spanned six to seven application platforms, each consisting of development, test, and production environments supporting business-critical workloads.\n\nThe migration process involved significantly more than simply converting Infrastructure as Code. Existing environments utilized AWS Aurora PostgreSQL Global Clusters deployed across multiple AWS regions, and many environments operated on different PostgreSQL major versions. Because the new Infrastructure as Code platform only supported specific PostgreSQL versions, I was responsible for planning and executing database version upgrades while accounting for AWS Aurora PostgreSQL upgrade path restrictions. Development environments often required multiple sequential major version upgrades before reaching the target version, while production and test environments required careful coordination to maintain availability and minimize operational risk.\n\nFor Aurora Global Database environments, I helped execute controlled upgrade procedures that included upgrading secondary regions, performing database switchovers, upgrading former primary regions, and restoring the original topology. These activities required extensive validation, coordination with application owners, and careful execution to ensure business continuity. Because these databases supported live production workloads, every migration required formal change management processes, deployment approvals, and close collaboration with the teams responsible for the applications relying on the databases.\n\nAs the first engineer on the team to successfully complete a full migration across development, test, and production environments, I helped establish the migration approach, validation procedures, deployment sequencing, and operational practices that were later adopted by the broader team. While automated conversion tools were available, many database parameters and environment-specific configurations required manual validation and updates. I frequently compared generated Infrastructure as Code configurations against existing AWS environments to ensure accuracy and prevent unintended infrastructure changes.\n\nOnce database versions and configurations were aligned with platform requirements, I deployed the new Infrastructure as Code framework and validated that the generated infrastructure matched the existing Aurora configuration. This approach allowed resources to transition to the new platform without unnecessary recreation while maintaining existing behavior and operational characteristics.\n\nIn addition to infrastructure modernization efforts, I participated in technical debt remediation initiatives, audited Go package dependencies, and developed unit tests for Go-based services. This engagement strengthened my experience with AWS Aurora PostgreSQL, Global Database architectures, Infrastructure as Code migrations, production change management, database upgrade planning, stakeholder coordination, Go development, and large-scale enterprise cloud modernization projects.', @@ -192,7 +194,7 @@ export const resumeHotspots: ResumeHotspot[] = [ }, { id: 'mayo-clinic', - match: 'Atos Client: Mayo Clinic', + match: 'Mayo Clinic |', title: 'Mayo Clinic', detail: 'As a Software Engineer Consultant supporting Mayo Clinic, I contributed to the development and modernization of a healthcare-focused platform utilizing React, GCP services, and Azure identity integrations. My primary responsibilities included developing a new user interface, implementing application enhancements, and supporting backend integrations within a cloud-native environment.\n\nA significant portion of my work involved integrating Azure App Registration-based authentication to support secure user access and identity management. I also worked with GCP services including BigQuery, Pub/Sub, and Artifact Registry while supporting application development and deployment activities across multiple environments.\n\nIn addition to feature development, I investigated and resolved CI/CD pipeline issues within Azure DevOps and assisted with application security remediation efforts, including addressing vulnerabilities related to third-party React package dependencies. I leveraged AI-assisted development tools such as Cursor to accelerate development, troubleshoot issues, and improve delivery efficiency.\n\nThis engagement provided experience working across multiple cloud platforms, combining frontend development, cloud services, identity integration, DevOps processes, and application security within a healthcare environment.', @@ -200,8 +202,8 @@ export const resumeHotspots: ResumeHotspot[] = [ }, { id: 'rag-project', - match: 'RAG Application', - title: 'RAG Application', + match: 'AI Agent-Powered RAG Platform', + title: 'AI Agent-Powered RAG Platform', detail: 'As a personal cloud and AI engineering project, I developed a Retrieval-Augmented Generation (RAG) application designed to answer questions using Tesla earnings call transcripts. The project was created to explore modern AI engineering concepts including embeddings, vector databases, semantic search, and large language model integration.\n\nThe solution utilized AWS Bedrock as the large language model platform, Amazon Titan Embeddings for vector generation, and ChromaDB as the vector database. Transcript data was processed, chunked into searchable documents, converted into embeddings, and stored within ChromaDB to support semantic retrieval. When users submitted questions, the application retrieved the most relevant transcript content and supplied it to the language model to generate grounded responses.\n\nA key focus of the project was understanding how retrieval quality impacts overall response accuracy. I experimented with document chunking strategies, embedding generation, and retrieval workflows to improve the relevance of retrieved content while reducing hallucinations. The project successfully demonstrated an end-to-end RAG architecture and provided hands-on experience with vector databases, embeddings, retrieval pipelines, and AWS Bedrock integration.\n\nThis project strengthened my understanding of modern AI application development and established a foundation for future work involving AI agents, automated workflows, and enterprise knowledge management systems.', link: 'https://github.com/TheTraille18/jet_rag_ai_project',