반응형
작성Tool: Google Script, Google Gemini
컨셉: 회사를 검색하면 최신 기사를 구글 API를 통해 조회하여 가져와서 RAG를 구축하고, 그 결과를 3줄 요약 및 제인 ITEM을 추출함
강점: RAG를 통해 할루시에이션을 막을 수 있음
결과물
미팅전에
B2B 영업 및 사업 기획 전용 인사이트 엔진
💡 RAG(Retrieval-Augmented Generation) 시스템 동작 원리
구글 LLM(Large Language Model)을 기반으로, 입력된 기업의 최신 비즈니스 기사 동향을 실시간 검색(Retrieval)합니다. 이후 AI(Artificial Intelligence)가 상상 없이 수집된 레퍼런스(Reference)만을 바탕으로 핵심 요약과 통신사 협력 인사이트를 생성(Augmented Generation)하여 팩트 기반의 정확한 미팅 준비를 지원합니다.
구글 LLM(Large Language Model)을 기반으로, 입력된 기업의 최신 비즈니스 기사 동향을 실시간 검색(Retrieval)합니다. 이후 AI(Artificial Intelligence)가 상상 없이 수집된 레퍼런스(Reference)만을 바탕으로 핵심 요약과 통신사 협력 인사이트를 생성(Augmented Generation)하여 팩트 기반의 정확한 미팅 준비를 지원합니다.
주요 키워드 및 최신 동향 요약
기업명을 입력하시면 분석이 시작됩니다.
통신사 협력 ITEM 제언 (아이디어)
맞춤형 제언 아이디어가 도출됩니다.
수집된 Reference 원문
분석에 활용된 원문 링크 목록입니다.
RAG PROCESS STATUS
1. 외부 DB 연동
(최신 뉴스 수집)
(최신 뉴스 수집)
2. LLM 컨텍스트 분석
(팩트 기반 추론)
(팩트 기반 추론)
3. 비즈니스 인사이트 완성
[Script 정리]
[HTML 정리]
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>미팅전에 - B2B 영업/사업 기획 전용 인사이트 엔진</title>
<style>
:root { --primary-color: #2b2b2b; --accent-color: #e6007e; --bg-gray: #f8f9fa; --border-color: #e9ecef; }
body { font-family: 'Pretendard', -apple-system, sans-serif; background-color: #f1f3f5; margin: 0; padding: 20px; color: #333; }
.biz-app-container { max-width: 1000px; margin: 0 auto; background: #ffffff; border-radius: 16px; padding: 45px; box-shadow: 0 15px 35px rgba(0,0,0,0.05); border: 1px solid var(--border-color); }
/* 타이틀 섹션 간격 조정 */
.header-section { text-align: center; margin-bottom: 30px; }
.header-title { font-size: 38px; font-weight: 900; color: #111; margin-bottom: 8px; letter-spacing: -1px; }
.sub-desc { color: #666; font-size: 16px; font-weight: 500; margin-bottom: 25px; }
.rag-info-box { background: #fdf4f9; border-left: 4px solid var(--accent-color); padding: 20px 25px; border-radius: 0 8px 8px 0; margin-bottom: 40px; text-align: left; font-size: 14.5px; color: #444; line-height: 1.6; }
.rag-info-box strong { color: var(--accent-color); font-size: 15px; }
.search-area { background: var(--bg-gray); padding: 30px; border-radius: 16px; margin-bottom: 40px; display: flex; gap: 15px; border: 1px solid #eee; }
.search-input { flex: 1; padding: 18px 25px; border: 2px solid #ddd; border-radius: 8px; font-size: 16px; outline: none; transition: 0.3s; }
.search-input:focus { border-color: var(--primary-color); background: #fff; box-shadow: 0 0 0 3px rgba(43,43,43,0.1); }
.search-btn { padding: 0 45px; background-color: var(--primary-color); color: white; border: none; border-radius: 8px; cursor: pointer; font-weight: 700; font-size: 16px; transition: 0.3s; }
.search-btn:hover { background-color: #000; transform: translateY(-2px); }
.content-layout { display: grid; grid-template-columns: 2fr 1fr; gap: 30px; }
.result-cards { display: flex; flex-direction: column; gap: 25px; }
.card { background: white; border: 1px solid var(--border-color); border-radius: 12px; padding: 30px; display: flex; flex-direction: column; min-height: 120px; box-shadow: 0 4px 15px rgba(0,0,0,0.02); }
.card-header { font-size: 18px; color: #111; margin-bottom: 20px; font-weight: 800; display: flex; align-items: center; }
.card-header::before { content: ""; width: 6px; height: 18px; background: var(--accent-color); margin-right: 12px; border-radius: 3px; }
.body-text { font-size: 15px; color: #444; line-height: 1.8; white-space: pre-wrap; word-break: keep-all; }
.feed-item { background: #fafafa; border-radius: 8px; padding: 20px; margin-bottom: 15px; border: 1px solid #f0f0f0; }
.feed-title { font-weight: 700; font-size: 15px; margin-bottom: 10px; color: #222; line-height: 1.5; word-break: keep-all; }
.feed-link { display: inline-block; color: #555; text-decoration: none; font-weight: 600; font-size: 13px; padding: 6px 14px; border-radius: 4px; border: 1px solid #ddd; background: #fff; transition: 0.2s; }
.feed-link:hover { background: #eee; color: #111; }
.label { font-size: 11px; font-weight: 800; padding: 4px 8px; border-radius: 4px; margin-bottom: 10px; display: inline-block; }
.lb-news { background: #e3f2fd; color: #1976d2; }
.rag-panel { background: #fff; border-radius: 12px; padding: 30px; text-align: center; border: 1px solid var(--border-color); height: fit-content; position: sticky; top: 20px; box-shadow: 0 4px 15px rgba(0,0,0,0.02); }
.rag-node { background: #f8f9fa; border: 1px solid #eee; border-radius: 8px; margin: 15px 0; padding: 18px 15px; font-size: 13.5px; color: #888; font-weight: 600; transition: 0.4s; }
.active-node { border-color: var(--primary-color); background: var(--primary-color); color: #fff; box-shadow: 0 6px 15px rgba(0,0,0,0.1); transform: translateY(-2px); }
</style>
</head>
<body>
<div class="biz-app-container">
<div class="header-section">
<div class="header-title">미팅전에</div>
<div class="sub-desc">B2B 영업 및 사업 기획 전용 인사이트 엔진</div>
</div>
<div class="rag-info-box">
<strong>💡 RAG(Retrieval-Augmented Generation) 시스템 동작 원리</strong><br>
구글 LLM(Large Language Model)을 기반으로, 입력된 기업의 <b>최신 비즈니스 기사 동향</b>을 실시간 검색(Retrieval)합니다. 이후 AI(Artificial Intelligence)가 상상 없이 수집된 레퍼런스(Reference)만을 바탕으로 핵심 요약과 통신사 협력 인사이트를 생성(Augmented Generation)하여 팩트 기반의 정확한 미팅 준비를 지원합니다.
</div>
<div class="search-area">
<input type="text" id="targetCompany" class="search-input" placeholder="미팅 예정 기업명을 입력하세요 (예: LG유플러스)">
<button class="search-btn" onclick="executeRAG()">인사이트 추출</button>
</div>
<div class="content-layout">
<div class="result-cards">
<div class="card">
<div class="card-header">주요 키워드 및 최신 동향 요약</div>
<div id="summaryArea" class="body-text" style="color:#aaa;">기업명을 입력하시면 분석이 시작됩니다.</div>
</div>
<div class="card">
<div class="card-header">통신사 협력 ITEM 제언 (아이디어)</div>
<div id="itemArea" class="body-text" style="color:#aaa;">맞춤형 제언 아이디어가 도출됩니다.</div>
</div>
<div class="card">
<div class="card-header">수집된 Reference 원문</div>
<div id="feedArea" style="min-height: 100px; color:#aaa;">분석에 활용된 원문 링크 목록입니다.</div>
</div>
</div>
<div class="rag-panel">
<div style="font-weight:800; color:#555; margin-bottom:20px; font-size:12px; letter-spacing:1px;">RAG PROCESS STATUS</div>
<div class="rag-node" id="r-news">1. 외부 DB 연동<br>(최신 뉴스 수집)</div>
<div class="rag-node" id="r-llm">2. LLM 컨텍스트 분석<br>(팩트 기반 추론)</div>
<div class="rag-node" id="r-done">3. 비즈니스 인사이트 완성</div>
</div>
</div>
</div>
<script>
function formatText(text) {
if (!text) return "내용 없음";
return text.replace(/\\n/g, '\n\n');
}
function executeRAG() {
const company = document.getElementById('targetCompany').value.trim();
if(!company) return alert('기업명을 정확히 입력해주세요.');
const loadingMsg = "데이터를 수집하고 분석 중입니다... (약 10초 소요)";
document.getElementById('summaryArea').innerText = loadingMsg;
document.getElementById('itemArea').innerText = "레퍼런스 기반 협력 아이템을 생성 중입니다...";
document.getElementById('feedArea').innerHTML = "최신 정보를 불러오는 중입니다...";
const areas = ['summaryArea', 'itemArea'];
areas.forEach(id => { document.getElementById(id).style.color = "#888"; });
resetNodes();
document.getElementById('r-news').classList.add('active-node');
google.script.run
.withSuccessHandler(function(data) {
document.getElementById('r-llm').classList.add('active-node');
if(data.error) {
document.getElementById('summaryArea').innerHTML = `<b style="color:#e6007e;">분석 오류:</b> ${data.error}`;
areas.forEach(id => { document.getElementById(id).style.color = "#333"; });
return;
}
document.getElementById('summaryArea').innerText = formatText(data.summary);
document.getElementById('itemArea').innerText = formatText(data.ideas);
areas.forEach(id => { document.getElementById(id).style.color = "#333"; });
if(data.news && data.news.length > 0) {
let feedHTML = "";
data.news.forEach(news => {
feedHTML += `
<div class="feed-item">
<span class="label lb-news">비즈니스 뉴스</span>
<div class="feed-title">${news.title}</div>
<a href="${news.link}" target="_blank" class="feed-link">원문 보기 ↗</a>
</div>`;
});
document.getElementById('feedArea').innerHTML = feedHTML;
}
document.getElementById('r-done').classList.add('active-node');
})
.withFailureHandler(function(error) {
document.getElementById('summaryArea').innerHTML = `<b style="color:#e6007e;">통신 오류:</b> 구글 서버와 연결할 수 없습니다.`;
document.getElementById('summaryArea').style.color = "#333";
})
.runAnalysis(company);
}
function resetNodes() {
['r-news', 'r-llm', 'r-done'].forEach(id => document.getElementById(id).classList.remove('active-node'));
}
</script>
</body>
</html>
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('Home')
.setTitle('Biz 미팅 준비 - LGU+ B2B 영업/사업 전용')
.addMetaTag('viewport', 'width=device-width, initial-scale=1')
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
function runAnalysis(query) {
if (!query) query = "LG유플러스";
// 고객님의 API 키
var geminiApiKey = "AIzaSyDCjD5VT_ny-mM_rWi3FRkKY2FEawcuA9w";
try {
// 순수 기업 비즈니스 동향 뉴스만 최대 5개까지 깊게 수집합니다.
var rssNews = UrlFetchApp.fetch("https://news.google.com/rss/search?q=" + encodeURIComponent(query + " 기업 비즈니스") + "&hl=ko&gl=KR&ceid=KR:ko");
var itemsNews = XmlService.parse(rssNews.getContentText()).getRootElement().getChild('channel').getChildren('item');
var newsList = [];
var referenceData = "[최신 비즈니스 뉴스 레퍼런스]\n";
for (var i = 0; i < Math.min(itemsNews.length, 5); i++) {
var title = itemsNews[i].getChild('title').getText();
var link = itemsNews[i].getChild('link').getText();
newsList.push({type: "News", title: title, link: link});
referenceData += "- " + title + "\n";
}
var prompt = "당신은 LG U+(엘지유플러스) Enterprise(엔터프라이즈) 고객그룹의 유능한 B2B(Business to Business) 영업 및 사업 기획 담당자입니다.\n" +
"수집된 최신 뉴스 Reference(레퍼런스)를 바탕으로 미팅 준비 자료를 작성해주세요.\n\n" +
"[수집된 Reference 데이터]\n" + referenceData + "\n\n" +
"[작성 지침]\n" +
"1. 절대 예측이나 상상하지 말고 수집된 데이터 팩트만 기반으로 작성하세요.\n" +
"2. 모든 IT 및 비즈니스 약어는 반드시 영어 Full Name(풀네임)을 함께 표기하세요.\n" +
"3. 가독성을 위해 반드시 줄바꿈(\\n)과 번호(1. 2. 3.) 또는 하이픈(-) 기호를 적극 사용하세요.";
var apiUrl = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=" + geminiApiKey;
var payload = {
"contents": [{"parts": [{"text": prompt}]}],
"generationConfig": {
"temperature": 0.1, // 팩트 기반이므로 창의성을 최소화
"maxOutputTokens": 8192,
"responseMimeType": "application/json",
"responseSchema": {
"type": "OBJECT",
"properties": {
"summary": { "type": "STRING", "description": "수집된 뉴스를 바탕으로 한 기업 동향 3줄 요약 (반드시 줄바꿈과 글머리 기호 사용)" },
"ideas": { "type": "STRING", "description": "요약된 맥락을 바탕으로 LG U+의 통신/Cloud(클라우드)/AI(Artificial Intelligence) 인프라를 활용한 비즈니스 협력 아이디어 3가지 제안 (반드시 줄바꿈과 글머리 기호 사용)" }
},
"required": ["summary", "ideas"]
}
}
};
var options = {
"method": "post",
"contentType": "application/json",
"payload": JSON.stringify(payload),
"muteHttpExceptions": true
};
var llmResponse = UrlFetchApp.fetch(apiUrl, options);
var llmData = JSON.parse(llmResponse.getContentText());
if (llmResponse.getResponseCode() !== 200 || llmData.error) {
return { error: llmData.error ? llmData.error.message : "API 오류 발생" };
}
var parsedLlmData = JSON.parse(llmData.candidates[0].content.parts[0].text);
return {
news: newsList,
summary: parsedLlmData.summary,
ideas: parsedLlmData.ideas
};
} catch (error) {
return { error: "서버 오류: " + error.toString() };
}
}
반응형