diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..93bca08 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,10 @@ +# 디폴트 무시된 파일 +/shelf/ +/workspace.xml +# 에디터 기반 HTTP 클라이언트 요청 +/httpRequests/ +# 쿼리 파일을 포함한 무시된 디폴트 폴더 +/queries/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/Source.iml b/.idea/Source.iml new file mode 100644 index 0000000..cbd9353 --- /dev/null +++ b/.idea/Source.iml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..9e2059a --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..6044bc3 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ollama/food.py b/ollama/food.py new file mode 100644 index 0000000..0f12334 --- /dev/null +++ b/ollama/food.py @@ -0,0 +1,47 @@ +from langchain_ollama import ChatOllama +from langchain_ibm import ChatWatsonx +from langchain_core.prompts import PromptTemplate, ChatPromptTemplate +from langchain_core.output_parsers import ( + StrOutputParser, + JsonOutputParser, + PydanticOutputParser, +) +from pydantic import BaseModel, Field +from typing import Literal +from dotenv import load_dotenv +import os +import gradio as gr + +qwen_llm = ChatOllama(model="qwen3.5:4b") +exaone_llm = ChatOllama(model="exaone3.5:2.4b") + +system_prompt = """\ + 당신은 20년 경력의 전문 셰프이자 요리 연구가입니다. + 사용자의 요리 질문에 대해 + 재료, 조리방법, 실패 방지 팁, 대체 재료를 + 포함하여 답변하세요. + 항상 한국어로 답변하세요 + """ + +template = ChatPromptTemplate.from_messages( + [ + ("system", system_prompt), + ("human", "{question}"), + ] +) + +chain = template | exaone_llm | StrOutputParser() + + +def chat(question, history): + response = chain.invoke({"question": question}) + return response + + +chatbot = gr.ChatInterface( + fn=chat, + title="🍝 요리 전문가", + description="요리경력 20년의 전문가입니다. 요리에 대한 궁금증을 해결하세요.", +) + +chatbot.launch() diff --git a/ollama/langchain.ipynb b/ollama/langchain.ipynb index f08f39c..2aeb318 100644 --- a/ollama/langchain.ipynb +++ b/ollama/langchain.ipynb @@ -1,40 +1,58 @@ { "cells": [ { - "cell_type": "code", - "execution_count": 2, + "cell_type": "markdown", "id": "97b6e429", "metadata": {}, - "outputs": [], "source": [ "### LLM 프레임워크" ] }, { "cell_type": "code", - "execution_count": null, - "id": "ceaff2f6", + "execution_count": 1, + "id": "fc77af84", "metadata": {}, "outputs": [], "source": [ - "from langchain_ollama import ChatOllama\n", - "from langchain_ibm import ChatWatsonx\n", - "from langchain_core.prompts import PromptTemplate, ChatPromptTemplate\n", - "from langchain_core.output_parsers import StrOutputParser, JsonOutputParser, PydanticOutputParser\n", - "from pydantic import BaseModel, Field\n", - "from typing import Literal\n", - "from dotenv import load_dotenv\n", - "import os\n", - "\n", - "type" + "#!pip install langchain-ollama langchain-ibm" ] }, { "cell_type": "code", - "execution_count": 14, - "id": "2e83941f", - "metadata": {}, + "id": "ceaff2f6", + "metadata": { + "ExecuteTime": { + "end_time": "2026-05-27T08:50:09.993923078Z", + "start_time": "2026-05-27T08:50:09.983490192Z" + } + }, + "source": [ + "#라이브러리 로드\n", + "\n", + "from langchain_ollama import ChatOllama\n", + "from langchain_ibm import ChatWatsonx\n", + "from langchain_core.prompts import PromptTemplate, ChatPromptTemplate\n", + "from langchain_core.output_parsers import StrOutputParser, JsonOutputParser, PydanticOutputParser\n", + "from langchain_core.runnables import RunnablePassthrough, RunnableParallel, RunnableLambda\n", + "from langchain_core.messages import HumanMessage, SystemMessage, AIMessage\n", + "from pydantic import BaseModel, Field\n", + "from typing import Literal\n", + "from dotenv import load_dotenv\n", + "import os" + ], "outputs": [], + "execution_count": 56 + }, + { + "cell_type": "code", + "id": "2e83941f", + "metadata": { + "ExecuteTime": { + "end_time": "2026-05-27T08:50:11.888281707Z", + "start_time": "2026-05-27T08:50:11.876005807Z" + } + }, "source": [ "# .env 내용 가져오기\n", "load_dotenv()\n", @@ -42,24 +60,21 @@ "apikey = os.getenv(\"WATSONX_API_KEY\")\n", "project_id = os.getenv(\"WATSONX_PROJECT_ID\")\n", "watsonx_ai_url = os.getenv(\"WATSONX_URL\")\n" - ] + ], + "outputs": [], + "execution_count": 57 }, { "cell_type": "code", - "execution_count": 36, - "id": "dc504bf8", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Hello! I'm an AI and don't have feelings, but I'm here and ready to assist you. How can I help you today?\n" - ] + "id": "7c0a9354", + "metadata": { + "ExecuteTime": { + "end_time": "2026-05-27T08:50:16.189743767Z", + "start_time": "2026-05-27T08:50:13.584144045Z" } - ], + }, "source": [ - "watson_lln = ChatWatsonx(\n", + "watson_llm = ChatWatsonx(\n", " model_id = \"ibm/granite-4-h-small\",\n", " url = f\"{watsonx_ai_url}\",\n", " api_key = f\"{apikey}\",\n", @@ -67,7 +82,55 @@ " max_tokens = 2000\n", ")\n", "\n", - "response = watson_lln.invoke(\"Hello, how are you?\")\n", + "qwen_llm = ChatOllama(model=\"qwen3.5:4b\")\n", + "exaone_llm = ChatOllama(model=\"exaone3.5:2.4b\")\n", + "gemma_llm = ChatOllama(model=\"gemma4:e2b\")" + ], + "outputs": [], + "execution_count": 58 + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c6fee268", + "metadata": {}, + "outputs": [], + "source": [ + "watson_llm = ChatWatsonx(\n", + " model_id = \"ibm/granite-4-h-small\",\n", + " url = f\"{watsonx_ai_url}\",\n", + " api_key = f\"{apikey}\",\n", + " project_id=f\"{project_id}\",\n", + " max_tokens = 2000\n", + ")\n", + "\n", + "qwen_llm = ChatOllama(model=\"qwen3.5:4b\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dc504bf8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello! As an AI, I don't have feelings, but I am here and ready to assist you. How may I help you today?\n" + ] + } + ], + "source": [ + "watson_llm = ChatWatsonx(\n", + " model_id = \"ibm/granite-4-h-small\",\n", + " url = f\"{watsonx_ai_url}\",\n", + " api_key = f\"{apikey}\",\n", + " project_id=f\"{project_id}\",\n", + " max_tokens = 2000\n", + ")\n", + "\n", + "response = watson_llm.invoke(\"Hello, how are you?\")\n", "print(response.content)" ] }, @@ -129,7 +192,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "id": "c1f464da", "metadata": {}, "outputs": [ @@ -163,7 +226,7 @@ } ], "source": [ - "qwen_llm = ChatOllama(model=\"exaone3.5:2.4b\")\n", + "exaone_llm = ChatOllama(model=\"exaone3.5:2.4b\")\n", "\n", "response = qwen_llm.invoke(\"생성형 AI를 설명해줘\")\n", "print(response.content)" @@ -223,7 +286,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 31, "id": "95d3e237", "metadata": {}, "outputs": [ @@ -231,9 +294,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "SQL Injection은 데이터베이스를 공격하는 한 방법으로, 공격자가 웹 애플리케이션의 데이터베이스에 악의적인 SQL 쿼리를 삽입하여 데이터를 조회, 변경, 삭제, 혹은 실행할 수 있는 위협입니다. 주로 사용자 입력을 통해 데이터베이스에 접근하는 웹 애플리케이션에 위험이 있습니다. 예를 들어, 로그인 폼에서 사용자 이름과 비밀번호를 입력할 때, 공격자가 SQL 쿼리를 조작하여 원하지 않은 데이터에 접근할 수 있습니다.\n", + "SQL Injection (SQL 주입)은 웹 어플리케이션에 대한 보안 취약점을 악용하여 악의적인 SQL 문을 넣어 데이터베이스에 직접 액세스하거나 조작하는 공격 방법입니다. 이는 입력 필드에서 사용자가 입력한 데이터를 검증하지 않고 직접 SQL 쿼리에 포함시키는 경우 발생할 수 있습니다.\n", "\n", - "SQL Injection 공격을 방지하기 위해서는 사용자 입력을 적절하게 검증하고, 파라미터화된 쿼리(statements)를 사용하며, 데이터베이스의 접근 권한을 최소화하는 등의 보안 조치가 필요합니다. 또한, 웹 애플리케이션에서 출력 데이터를 검증하고 정제하여 크로스 사이트 스크립팅(XSS) 공격 방지에도 도움이 됩니다.\n" + "예를 들어, 웹 사이트의 로그인 페이지에서 사용자 이름과 비밀번호를 입력 받는 경우, 입력된 데이터를 검증하지 않고 \"SELECT * FROM users WHERE username = 'user_input' AND password = 'password_input'\"와 같은 SQL 쿼리를 만들어 데이터베이스에서 사용자 정보를 가져옵니다. 하지만 이 경우, 공격자가 사용자 이름에 \"' OR '1'='1\"와 같은 SQL 문을 입력하면, 이는 \"SELECT * FROM users WHERE username = '' OR '1'='1' AND password = 'password_input'\"로 변환되어 항상 참인 SQL 문이 되어 모든 사용자 정보를 가져올 수 있게 됩니다.\n", + "\n", + "이러한 SQL Injection 공격을 방지하기 위해 입력 데이터의 검증과 이스케이프, 또는 준비된 문장(prepared statement) 등의 방법을 사용하여 SQL 쿼리를 안전하게 작성하는 것이 중요합니다. 또한, 최신 보안 기술과 업데이트를 적용하고, 정기적인 보안 감사와 테스트를 수행하는 것이 필요합니다.\n" ] } ], @@ -246,25 +311,49 @@ "\"\"\")\n", "\n", "formatted_prompt = template.format(question=\"SQL Injection 이란?\")\n", - "response = watson_lln.invoke(formatted_prompt)\n", + "response = watson_llm.invoke(formatted_prompt)\n", "print(response.content)" ] }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 32, "id": "9537894c", "metadata": {}, "outputs": [ { - "ename": "NameError", - "evalue": "name 'exaone_llm' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[31m---------------------------------------------------------------------------\u001b[39m", - "\u001b[31mNameError\u001b[39m Traceback (most recent call last)", - "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[38]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m response = exaone_llm.invoke(formatted_prompt)\n\u001b[32m 2\u001b[39m print(response.content)\n", - "\u001b[31mNameError\u001b[39m: name 'exaone_llm' is not defined" + "name": "stdout", + "output_type": "stream", + "text": [ + "SQL Injection은 **데이터베이스 쿼리에 악의적인 코드를 삽입하여 데이터베이스 시스템을 조작하거나 데이터 접근을 권한을 벗어난 방식으로 변경하려는 사이버 공격 기법**입니다. \n", + "\n", + "**핵심 특징:**\n", + "\n", + "* **SQL 언어 악용:** 표준 SQL 문법과 구문을 악용하여 악의적인 SQL 코드를 데이터베이스 쿼리에 주입합니다.\n", + "* **입력 필드 악용:** 웹 애플리케이션의 사용자 입력 필드 (예: 검색 엔진, 로그인 폼 등) 를 통해 공격자는 악의적인 코드를 삽입할 수 있습니다.\n", + "* **파라미터화된 쿼리 무시:** 안전한 파라미터화된 쿼리 사용 없이 실행될 경우 심각한 보안 취약점이 됩니다. 파라미터화된 쿼리는 입력 값을 SQL 문자열과 분리하여 처리하므로 악의적인 코드 삽입을 방지할 수 있습니다.\n", + "* **권한 악용:** 공격자는 injected 코드를 통해 데이터베이스에 대한 무단 접근, 데이터 삭제, 수정, 또는 전체 시스템 제어를 시도할 수 있습니다.\n", + "\n", + "**예시:**\n", + "\n", + "```sql\n", + "SELECT * FROM users WHERE username = '$username' AND password = '$password'; \n", + "```\n", + "\n", + "공격자가 다음과 같이 입력할 경우:\n", + "\n", + "```\n", + "username: admin' --'password:anything\n", + "```\n", + "\n", + "쿼리는 `admin` username을 통해 모든 사용자 정보에 접근하게 되어 데이터 유출 등의 문제를 야기할 수 있습니다.\n", + "\n", + "**예방책:**\n", + "\n", + "* **입력 검증 및 필터링:** 모든 사용자 입력을 엄격하게 검증하고 필터링하여 SQL 메타 문자를 제거하거나 이스케이프 처리합니다.\n", + "* **파라미터화된 쿼리 사용:** SQL 쿼리에 입력 값을 분리하여 처리하는 파라미터화된 쿼리를 사용하여 SQL Injection 취약점을 최소화합니다.\n", + "* **웹 애플리케이션 보안 업데이트:** 최신 보안 패치를 적용하여 취약점을 해결합니다.\n", + "* **정규 표현식 활용:** SQL 메타 문자 패턴을 차단하는 정규 표현식을 사용합니다.\n" ] } ], @@ -287,7 +376,7 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": null, "id": "b7a9dbc0", "metadata": {}, "outputs": [ @@ -323,13 +412,13 @@ "\"\"\")\n", "\n", "formatted_prompt = template.format(question=\"SQL Injection 이란?\")\n", - "response = watson_lln.invoke(formatted_prompt)\n", + "response = watson_llm.invoke(formatted_prompt)\n", "print(response.content)" ] }, { "cell_type": "code", - "execution_count": 44, + "execution_count": null, "id": "24d4bcdb", "metadata": {}, "outputs": [ @@ -380,7 +469,7 @@ ")\n", "\n", "formatted_prompt = template.format(role = \"파이썬\", language=\"한국어\", question=\"리스트 컴프리헨션이란?\")\n", - "response = watson_lln.invoke(formatted_prompt)\n", + "response = watson_llm.invoke(formatted_prompt)\n", "print(response.content)" ] }, @@ -392,12 +481,18 @@ "#### LCEL 파이프라인\n", "- LCEL(LangChain Expression Language) : | 연산자로 컴포넌트를 연결하는 파이프라인 문법\n", " - ex) prompt | llm | parser => 왼쪽에서 오른쪽으로 데이터가 흐르게(처리) 됨\n", + " - RunnableSequece 생성\n", + " - RunnablePassthrough : 입력을 그대로 통과시키며 다른 키와 병합할 때 사용\n", + " - RunaableLambda : 체인을 파이썬 함수와 연결\n", + " - RunaableParallel : 여러 체인을 동시에 실행하고 결과를 dict 병합할 때 사용\n", + " - .assign() : 체인 중간에 새 키를 추가\n", + "\n", "- invoke() : 단일 동기 호출 / stream() : 스트리밍 / batch() : 여러 입력 병렬 처리" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 33, "id": "a38e8147", "metadata": {}, "outputs": [ @@ -405,11 +500,16 @@ "name": "stdout", "output_type": "stream", "text": [ - "XSS(크로스-사이트 스크립팅)는 웹 보안 취약점 중 하나로, 악의적인 스크립트 코드를 웹 페이지에 삽입하여 사용자의 정보를 탈취하거나 웹사이트를 조작하는 공격입니다. XSS 공격을 통해 공격자는 사용자의 세션 정보, 쿠키, 로그인 정보 등을 탈취할 수 있으며, 이를 통해 사용자의 계정을 훔쳐 사용하거나 개인 정보를 수집할 수 있습니다.\n", + "XSS는 Cross-Site Scripting의 약자로, 웹사이트와 웹 애플리케이션에서 발생할 수 있는 보안 취약점을 의미합니다. XSS는 공격자가 다른 사용자들의 브라우저에서 악의적인 스크립트를 실행시키는데 사용되며, 이를 통해 데이터를 탈취, 웹사이트에 불법적인 데이터를 삽입하거나 기타 악의적인 작업을 수행할 수 있습니다.\n", "\n", - "XSS 공격은 주로 웹사이트에 입력 폼이나 다른 사용자가 입력한 데이터가 포함된 곳에 악의적인 스크립트 코드를 삽입하는 방식으로 이루어집니다. 이 스크립트 코드는 다른 사용자가 해당 웹 페이지를 방문할 때 실행되어 개인 정보를 탈취하거나 웹 페이지의 내용을 변경하는 등의 악의적인 행동을 수행할 수 있습니다.\n", + "주로 XSS는 웹 애플리케이션이 사용자의 입력을 검증하지 않고 출력하는 경우에 발생합니다. 공격자는 이를 차용하여 악성 스크립트를 보낼 수 있고, 다른 사용자들이 해당 스크립트를 실행하게 되면 공격이 성공합니다.\n", "\n", - "XSS 공격에 대한 대책으로는 웹 개발자가 사용자 입력을 적절히 검증하고, 출력 시에 적절한 인코딩을 수행하여 악의적인 스크립트가 실행되지 않도록 해야 합니다. 또한 사용자는 신뢰할 수 있는 웹사이트만 방문하고, 브라우저의 보안 기능을 최대한 활용하는 것이 중요합니다.\n" + "XSS는 두 가지 주요 타입으로 나눌 수 있습니다:\n", + "\n", + "1. Reflected XSS: 사용자가 악의적인 스크립트가 포함된 요청을 서버로 전송할 때마다 서버가 해당 스크립트를 클라이언트에 다시 반사하여 실행되는 경우입니다. 예를 들어, 사용자가 악성 링크를 클릭하거나 악성 폼을 제출하는 경우에 해당합니다.\n", + "2. Stored XSS: 공격자가 악성 스크립트를 웹사이트의 데이터베이스나 기타 영구 저장소에 저장한 후, 웹 애플리케이션이 이 데이터를 출력할 때마다 해당 스크립트를 모든 사용자에게 전송하는 경우입니다. 예를 들어, 게시판에 악성 스크립트를 쓰거나 프로필에 악성 스크립트를 포함시키는 경우에 해당합니다.\n", + "\n", + "위와 같은 XSS 공격을 방지하기 위해서는 입력 데이터를 검증하고 출력 데이터를 제대로 이스케이프 처리해야 합니다.\n" ] } ], @@ -431,13 +531,1452 @@ "\n", "print(response.content)" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ed43fc8f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "XSS는 크로스 사이트 스크립팅(Cross-Site Scripting)을 의미합니다. XSS는 웹 애플리케이션에 발생할 수 있는 보안 취약점으로, 악의적인 스크립트를 웹 페이지에 삽입하여 사용자의 웹 브라우저에서 실행되도록 하는 공격 기법입니다.\n", + "\n", + "XSS 공격은 웹 페이지에 사용자 입력 데이터를 그대로 출력할 때 발생하며, 악의적인 스크립트를 사용자가 입력하면 해당 스크립트가 다른 사용자의 웹 브라우저에서 실행되어 개인 정보를 탈취하거나 웹사이트를 조작하는 등의 피해를 유발할 수 있습니다.\n", + "\n", + "XSS는 주로 두 가지 형태로 분류됩니다:\n", + "\n", + "1. Reflected XSS: 사용자 입력 데이터가 서버에서 즉시 반영되고, 그 결과가 웹 페이지에 표시되는 경우에 발생합니다. 예를 들어, 악의적인 스크립트가 포함된 URL을 클릭하면 해당 스크립트가 페이지에 삽입되어 실행됩니다.\n", + "2. Stored XSS: 사용자 입력 데이터가 서버에 저장되고, 나중에 다른 사용자가 그 데이터를 읽을 때 악의적인 스크립트가 실행되는 경우에 발생합니다. 예를 들어, 게시판이나 댓글에 악의적인 스크립트를 작성하여 저장하면, 다른 사용자가 그 게시물을 읽을 때 스크립트가 실행됩니다.\n", + "\n", + "XSS 공격을 방지하기 위해 웹 개발자는 사용자 입력 데이터를 제대로 검증하고, 출력할 때는 필요한 경우에는 이스케이프 처리를 수행해야 합니다. 또한, Content Security Policy(CSP)와 같은 보안 기능을 활용하여 스크립트 실행을 제한하거나 웹사이트의 보안을 강화할 수 있습니다.\n" + ] + } + ], + "source": [ + "# 메시지를 string으로 처리\n", + "\n", + "parser = StrOutputParser()\n", + "\n", + "chain = prompt | watson_llm | parser\n", + "\n", + "response = chain.invoke({\n", + " 'role' : '보안',\n", + " 'question' : 'xss란?'\n", + "})\n", + "\n", + "print(response)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f1d6be58", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "XSS(크로스 사이트 스크립팅 공격, Cross-Site Scripting)는 웹 애플리케이션의 취약점을 이용하여 악성 스크립트를 사용자의 웹 브라우저에 삽입하는 공격 방식입니다. 이 공격을 통해 공격자는 사용자의 세션 정보, 쿠키, 기타 개인 정보를 탈취하거나 사용자의 행동을 조작할 수 있습니다.\n", + "XSS 공격은 주로 다음과 같은 세 가지 유형으로 분류됩니다.\n", + "\n", + "1. 반사형 XSS(Reflected XSS): 사용자가 올바르지 않은 입력을 제출할 때마다 발생합니다. 이 경우 공격자는 사용자에게 악성 스크립트가 포함된 링크를 보내고, 사용자가 해당 링크를 클릭하면 악성 스크립트가 실행됩니다.\n", + "2. 저장형 XSS(Stored XSS): 웹 서버의 데이터베이스에 악성 스크립트가 저장되어 사용자에게 전송됩니다. 이 경우 공격자는 악성 스크립트를 웹 사이트에 게시하고, 다른 사용자가 해당 페이지를 방문할 때 악성 스크립트가 실행됩니다.\n", + "3. DOM 기반 XSS(DOM-based XSS): 클라이언트 측 스크립트(예: JavaScript)가 실행되는 동안 발생합니다. 이 경우 공격자는 악성 스크립트를 웹 사이트에 삽입하고, 웹 브라우저가 해당 스크립트를 실행하면서 웹 페이지의 DOM(문서 개체 모델)이 변경됩니다.\n", + "\n", + "XSS 공격을 방어하기 위한 방법으로는 다음과 같은 기술들이 있습니다.\n", + "\n", + "* 입력 검증(Input Validation): 사용자 입력을 검증하고, 올바르지 않은 입력에 대한 필터링을 수행합니다.\n", + "* 출력 인코딩(Output Encoding): 사용자의 입력을 출력할 때 HTML, JavaScript 및 기타 스크립트 언어에 대한 인코딩을 수행하여 악성 코드가 실행되지 않도록 방어합니다.\n", + "* Content Security Policy(CSP): 웹 브라우저에 대한 보안 정책을 설정하여, 악성 스크립트 실행을 제한합니다.\n", + "* HTTPOnly 쿠키: 쿠키에 HTTPOnly 플래그를 설정하여, 자바스크립트를 통해 쿠키에 접근하지 못하도록 합니다." + ] + } + ], + "source": [ + "chain = prompt | watson_llm | parser\n", + "\n", + "for chunk in chain.stream({ \"role\" : '보안', \"question\" : \"XSS란?\"}):\n", + " print(chunk, end='', flush=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c96cc1a0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "XSS는 Cross-Site Scripting의 약자로, 웹 애플리케이션의 보안 취약점을 의미합니다. 이 취약점은 악의적인 스크립트를 웹 페이지에 삽입하여 사용자의 브라우저에서 실행되게 하여, 보안 위반, 데이터 유출, 브라우저 제어 등의 문제를 일으킬 수 있습니다.\n", + "\n", + "XSS는 크게 두 가지 종류가 있습니다:\n", + "\n", + "1. Reflected XSS (Reflected Cross-Site Scripting): 사용자가 입력하는 데이터를 서버에 전송하고, 서버가 그 데이터를 웹 페이지에 반영할 때 스크립트를 삽입하는 공격입니다. 보통 악의적인 링크를 통해 공격을 시도하는데, 사용자가 이 링크를 클릭하면 XSS 코드가 실행됩니다.\n", + "2. Stored XSS (Stored Cross-Site Scripting): 웹 서버에 악성 스크립트가 저장되어 있고, 사용자가 해당 웹 페이지를 방문할 때 악성 스크립트가 실행되는 공격입니다. 이 경우에는 주로 게시판, 댓글, 고객 리뷰 등과 같이 사용자가 입력한 데이터가 다른 사용자들에게도 보여지는 곳에서 발생합니다.\n", + "\n", + "XSS 공격을 방지하기 위해 개발자는 사용자 입력 데이터를 적절하게 검증하고 처리해야 합니다. 이를 위해 데이터 검증, 출력 이스케이프, Content Security Policy (CSP) 등의 기술을 사용할 수 있습니다.\n", + "파이썬에서 리스트(List)는 가장 일반적으로 사용되는 자료구조 중 하나입니다. 리스트는 다양한 자료형을 포함할 수 있는 순서가 있는 컬렉션으로, 원소들을 쉽게 추가, 삭제, 수정할 수 있습니다. 리스트는 대괄호 `[ ]` 로 둘러싸여 있으며, 원소들은 쉼표 `,` 로 구분됩니다.\n", + "\n", + "특징:\n", + "\n", + "1. 원소들은 인덱스를 통해 접근할 수 있으며, 인덱스는 0부터 시작합니다. 예를 들어, `my_list[0]`은 리스트의 첫 번째 원소에 접근합니다.\n", + "2. 리스트는 가변(Mutable) 자료형입니다. 즉, 리스트 안에 있는 원소들을 수정, 추가, 삭제할 수 있습니다.\n", + "3. 리스트는 정렬되어 있으며, 중복된 원소를 포함할 수 있습니다.\n", + "4. 리스트는 이터러블(Iterable)이며, `for` 루프 등의 반복문에서 사용할 수 있습니다.\n", + "5. 리스트는 다양한 내장 함수와 메소드를 지원하여 원소를 추가, 삭제, 조작하는 등의 다양한 작업을 수행할 수 있습니다.\n", + "\n", + "예시:\n", + "```python\n", + "my_list = [1, 2, 3, 4, 5] # 정수 리스트\n", + "mixed_list = [1, \"Hello\", 3.14, True] # 혼합 자료형 리스트\n", + "empty_list = [] # 빈 리스트\n", + "\n", + "# 리스트에 원소 추가\n", + "my_list.append(6)\n", + "# 리스트에서 원소 삭제\n", + "my_list.remove(3)\n", + "# 리스트에서 특정 인덱스에 있는 원소 접근\n", + "element = my_list[2]\n", + "```\n", + "Python에서 딕셔너리(Dictionary)는 키(Key)와 값(Value)의 쌍으로 이루어진 컬렉션(Collection) 자료형입니다. 딕셔너리는 다른 프로그래밍 언어에서 해시 테이블(hash table)이라고 불리는 자료 구조와 유사합니다. 파이썬 딕셔너리는 중괄호 `{}`를 사용하여 정의되며, 각 항목은 콤마 `,`로 구분됩니다.\n", + "\n", + "딕셔너리의 예시는 다음과 같습니다:\n", + "\n", + "```python\n", + "my_dict = {\n", + " \"name\": \"John\",\n", + " \"age\": 30,\n", + " \"city\": \"New York\"\n", + "}\n", + "```\n", + "\n", + "여기서 `name`, `age`, `city`는 키(Key)이고, 각각 \"John\", 30, \"New York\"는 해당 키에 연결된 값(Value)입니다. 딕셔너리에서 키는 고유(unique)해야 하며, 해시 가능한(hashable) 타입이어야 합니다. 값은 어떤 자료형이든 가능합니다.\n", + "\n", + "딕셔너리를 다룰 때 사용되는 주요 메소드와 연산자는 다음과 같습니다:\n", + "\n", + "1. `my_dict[key]` - 해당 키에 대한 값을 조회하거나 할당합니다. 키가 존재하지 않으면 KeyError가 발생할 수 있습니다.\n", + "2. `my_dict.get(key, default_value)` - 해당 키에 대한 값을 조회합니다. 키가 존재하지 않으면 default_value를 반환합니다.\n", + "3. `my_dict[key] = value` - 새로운 키-값 쌍을 추가하거나 기존 키에 대한 값을 업데이트합니다.\n", + "4. `del my_dict[key]` - 특정 키와 해당 값을 딕셔너리에서 제거합니다.\n", + "5. `len(my_dict)` - 딕셔너리의 크기(항목 수)를 반환합니다.\n", + "6. `key in my_dict` - 특정 키가 딕셔너리에 존재하는지 확인합니다.\n", + "\n", + "Python 딕셔너리는 효율적인 데이터 검색과 구성 변경에 유용하며, 다양한 상황에서 유연하게 사용됩니다.\n", + "자바에서 클래스(Class)는 객체(Object)의 템플릿 또는 설계도입니다. 클래스는 객체 지향 프로그래밍(OOP)의 핵심 개념으로, 데이터(속성, 필드, 변수)와 함수(메소드, 동작)를 하나의 단위로 묶어서 사용합니다. 클래스는 객체를 생성하고 조작하기 위한 청사진이며, 객체는 클래스의 인스턴스입니다.\n", + "\n", + "클래스는 다음과 같은 요소를 포함할 수 있습니다:\n", + "\n", + "1. 필드(Fields): 클래스의 상태를 나타내는 변수입니다. 객체가 가지고 있는 데이터를 저장합니다.\n", + "2. 메소드(Methods): 클래스의 행동을 정의하는 함수입니다. 객체가 수행할 수 있는 동작을 나타냅니다.\n", + "3. 생성자(Constructor): 객체가 생성될 때 초기화를 담당하는 특별한 메소드입니다. 클래스와 같은 이름을 가지며 리턴 타입이 없습니다.\n", + "\n", + "클래스를 사용하여 객체를 생성하려면 'new' 키워드를 사용하여 클래스의 인스턴스를 생성합니다. 객체는 클래스를 통해 생성되며, 클래스의 정의에 따라 속성과 메소드를 가지게 됩니다.\n", + "\n", + "예를 들어, \"Car\"라는 클래스를 정의한다면, 이 클래스는 'brand', 'color', 'speed'와 같은 필드와 'startEngine()', 'changeGear()', 'stop()'과 같은 메소드를 가질 수 있습니다. 그리고 \"Car\" 클래스를 사용하여 \"toyota\", \"bmw\", \"audi\"와 같은 여러 클래스 인스턴스를 만들 수 있습니다. 각 인스턴스는 'brand', 'color', 'speed'와 같은 고유한 속성 값을 가질 수 있으며, 'startEngine()', 'changeGear()', 'stop()'과 같은 메소드를 호출하여 동작을 수행할 수 있습니다.\n" + ] + } + ], + "source": [ + "# batch() : 여러 입력 병렬 처리\n", + "\n", + "chain = prompt | watson_llm | parser\n", + "\n", + "results = chain.batch([\n", + " { \"role\" : '보안', \"question\" : \"XSS란?\"},\n", + " { \"role\" : '파이썬', \"question\" : \"리스트란?\"},\n", + " { \"role\" : '파이썬', \"question\" : \"딕셔너리란?\"},\n", + " { \"role\" : '자바', \"question\" : \"클래스란?\"},\n", + "\n", + "])\n", + "\n", + "for result in results:\n", + " print(result)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1d6e9a2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "XSS (Cross-Site Scripting)는 웹 보안 위협 중 하나로, 공격자가 웹사이트를 통해 사용자에게 악의적인 스크립트 코드를 주입하는 기법을 말합니다. 주요 특징과 종류는 다음과 같습니다:\n", + "\n", + "### 정의:\n", + "- **정의**: XSS는 웹 애플리케이션이 사용자 입력을 적절히 필터링하거나 처리하지 않아, 공격자가 사용자의 브라우저에 악의적인 스크립트를 실행시킬 수 있게 만드는 보안 취약점입니다.\n", + "\n", + "### 주요 특징:\n", + "1. **출처 다양성**:\n", + " - **Reflected XSS**: 사용자 입력이 URL을 통해 직접적으로 반영되어 웹 페이지에 포함될 때 발생합니다. 예를 들어, 악성 링크를 클릭하면 사용자의 브라우저에서 스크립트가 실행됩니다.\n", + " - **Stored XSS**: 웹사이트가 데이터를 저장할 때 악성 코드를 적절히 필터링하지 않고 그대로 저장하여 다른 사용자들이 접근할 때 실행됩니다. 예를 들어, 댓글 섹션이나 게시판에 악성 스크립트가 포함될 수 있습니다.\n", + " - **DOM-Based XSS**: 클라이언트 측 자바스크립트가 사용자 입력을 처리하지 않고 그대로 DOM(Document Object Model)에 삽입함으로써 발생합니다. 주로 브라우저 내부에서 악의적인 동작을 수행합니다.\n", + "\n", + "### 영향:\n", + "- **사용자 정보 탈취**: 세션 쿠키나 개인 정보를 탈취할 수 있습니다.\n", + "- **사이트 조작**: 사용자의 행동을 조작하거나 웹사이트의 내용을 변경할 수 있습니다.\n", + "- **사용자 인터페이스 손상**: 웹사이트의 정상적인 동작을 방해하거나 사용자 경험을 저하시킬 수 있습니다.\n", + "\n", + "### 방어 전략:\n", + "- **입력 필터링**: 사용자 입력을 엄격하게 필터링하고 HTML 엔코딩을 적용합니다.\n", + "- **Content Security Policy (CSP)**: 웹 페이지에서 실행 가능한 자원의 출처를 제한합니다.\n", + "- **HTTP 헤더 설정**: `X-XSS-Protection` 헤더를 사용하여 브라우저의 내장 XSS 필터를 활성화합니다.\n", + "- **서버 측 검증**: 가능한 모든 데이터 검증을 서버 측에서 수행합니다.\n", + "- **안전한 라이브러리 사용**: 자바스크립트 라이브러리나 프레임워크의 보안 기능을 활용합니다.\n", + "\n", + "XSS 공격은 매우 위험할 수 있으므로, 웹 개발자와 관리자는 이러한 취약점을 최소화하기 위한 지속적인 모니터링과 보안 업데이트가 필수적입니다.\n", + "리스트는 프로그래밍에서 매우 중요한 데이터 구조 중 하나로, **순서가 있는 항목들의 컬렉션**을 의미합니다. 파이썬을 포함한 여러 프로그래밍 언어에서 리스트를 사용하며, 다음과 같은 주요 특징을 가지고 있습니다:\n", + "\n", + "1. **순서**: 리스트의 가장 기본적인 특징은 요소들이 특정 순서로 정렬되어 있다는 것입니다. 즉, 첫 번째 요소가 마지막 요소보다 항상 앞에 위치합니다 (인덱스는 0부터 시작).\n", + "\n", + "2. **동적 크기**: 리스트는 생성된 후에도 요소를 추가하거나 제거할 수 있는 **동적 크기**를 가지고 있습니다. 이는 프로그램의 요구에 따라 유연하게 확장 또는 축소할 수 있다는 장점이 있습니다.\n", + "\n", + "3. **다양한 자료형**: 리스트는 동일한 타입의 데이터만 저장할 수 있는 것이 아니라, **다양한 타입의 데이터**를 혼합하여 저장할 수 있습니다. 예를 들어, 숫자, 문자열, 불리언 값 등을 함께 넣을 수 있습니다.\n", + "\n", + "4. **인덱싱 및 슬라이싱**: 파이썬에서는 리스트를 쉽게 접근하고 조작할 수 있는 기능들이 제공됩니다.\n", + " - **인덱싱**: 특정 위치의 요소에 접근하기 위해 `[인덱스]` 형태로 사용합니다. 인덱스는 0부터 시작하며, 리스트의 마지막 요소는 `-1`, 그 전 요소는 `-2` 등으로 참조할 수 있습니다.\n", + " - **슬라이싱**: `[시작:끝:스텝]` 형태로 특정 범위의 요소들을 선택합니다. 기본값은 `0:None`으로 전체 요소를 반환하며, `-1`을 스텝으로 사용하면 마지막 요소부터 접근 가능합니다.\n", + "\n", + "5. **멀티디미셔널**: 파이썬에서 리스트는 내장 타입을 넘어 객체들을 포함하는 **멀티디미셔널** 데이터 구조로도 사용될 수 있습니다. 즉, 리스트 내의 요소들이 각각 다른 데이터 타입일 수 있습니다.\n", + "\n", + "예를 들어, 파이썬 코드로 리스트를 생성하고 사용하는 방법은 다음과 같습니다:\n", + "\n", + "```python\n", + "# 리스트 생성\n", + "numbers = [1, 2, 3, 4, 5] # 정수 리스트\n", + "fruits = [\"apple\", \"banana\", \"cherry\"] # 문자열 리스트\n", + "mixed_list = [1, \"hello\", True] # 다양한 타입의 요소 포함 리스트\n", + "\n", + "# 인덱싱\n", + "print(numbers[0]) # 첫 번째 요소 출력: 1\n", + "print(fruits[-2]) # 두 번째 마지막 요소 출력: cherry\n", + "\n", + "# 슬라이싱\n", + "print(numbers[1:4]) # 두 번째부터 네 번째 요소까지 출력: [2, 3, 4]\n", + "\n", + "# 요소 추가 및 제거\n", + "numbers.append(6) # 리스트 끝에 요소 추가\n", + "numbers.remove(3) # 특정 요소 제거\n", + "```\n", + "\n", + "리스트는 데이터 관리와 처리에서 매우 유용한 도구로, 반복 작업, 데이터 필터링, 그리고 복잡한 구조를 단순화하는 데 자주 활용됩니다.\n", + "딕셔너리(Dictionary)는 파이썬 프로그래밍 언어에서 매우 중요한 데이터 구조 중 하나입니다. 딕셔너리는 **키(Key)**와 **값(Value)**의 쌍으로 이루어진 Collections 형태입니다. 주요 특징과 사용법은 다음과 같습니다:\n", + "\n", + "### 주요 특징:\n", + "1. **키와 값의 쌍**: 각 키는 유일해야 하며, 이를 통해 해당 키에 연결된 값을 빠르게 접근할 수 있습니다.\n", + "2. **키 타입 다양성**: 키는 문자열뿐만 아니라 숫자나 다른 데이터 타입(예: 튜플, 리스트 등)도 될 수 있습니다. 하지만 일반적으로 문자열이 가장 흔합니다.\n", + "3. **무순서**: 파이썬 3.7부터 딕셔너리는 삽입 순서를 기억하는 기능이 추가되었습니다. 즉, `dict` 객체가 생성된 시점의 삽입 순서를 유지합니다. 이전 버전에서는 완전히 순서를 보장하지 않았습니다.\n", + "4. **다양성**: 다양한 내장 함수와 메서드를 지원하여 효율적인 데이터 관리와 조작이 가능합니다.\n", + "\n", + "### 예시 사용법:\n", + "```python\n", + "# 기본적인 딕셔너리 생성\n", + "person = {\n", + " 'name': 'Alice',\n", + " 'age': 30,\n", + " 'occupation': 'Engineer'\n", + "}\n", + "\n", + "# 접근\n", + "print(person['name']) # 출력: Alice\n", + "print(person['age']) # 출력: 30\n", + "\n", + "# 값 추가 또는 수정\n", + "person['age'] = 31 # 기존 값 업데이트\n", + "person['location'] = 'New York' # 새로운 키-값 쌍 추가\n", + "\n", + "# 키 존재 여부 확인\n", + "if 'name' in person:\n", + " print(\"Name exists in dictionary\")\n", + "\n", + "# 키 삭제\n", + "del person['occupation'] # 딕셔너리에서 키 삭제 가능\n", + "\n", + "# 딕셔너리 길이 확인\n", + "print(len(person)) # 출력: 3\n", + "```\n", + "\n", + "### 활용 예시:\n", + "- **데이터 매핑**: 사용자 정보, 제품 정보 등 다양한 종류의 데이터를 빠르게 접근할 때 유용합니다.\n", + "- **중복 처리**: 여러 항목에 대해 고유한 식별자(키)를 사용하여 값을 저장할 수 있습니다.\n", + "- **효율적인 데이터 검색**: 키 기반 검색이 O(1) 평균 시간 복잡도로 이루어지기 때문에 빠른 데이터 처리가 가능합니다.\n", + "\n", + "딕셔너리는 파이썬 프로그래밍에서 매우 유연하고 강력한 도구로, 다양한 시나리오에서 데이터 관리에 필수적으로 사용됩니다.\n", + "클래스는 객체 지향 프로그래밍의 핵심 개념 중 하나로, **데이터(속성)와 그 데이터를 조작하는 기능(메서드)을 하나의 포장된 단위로 묶어 관리하는 설계도 또는 템플릿**입니다. 쉽게 말해, 클래스는 **\"무엇\"과 그 \"무엇을 어떻게 사용할 수 있는가\"를 정의하는 추상화된 개념**입니다.\n", + "\n", + "**핵심 특징:**\n", + "\n", + "* **데이터 캡슐화:** 클래스 내부의 데이터를 직접 접근하지 못하도록 보호합니다. 데이터는 클래스 내부에 정의되며, 외부에서 접근하기 위해서는 클래스가 제공하는 메서드를 통해야 합니다. 이를 통해 데이터의 안정성과 일관성을 유지할 수 있습니다.\n", + "* **코드 재사용:** 하나의 클래스를 여러 개의 객체로 생성하여 코드를 재사용할 수 있습니다. 이는 코드의 중복을 줄이고 유지 보수를 용이하게 합니다.\n", + "* **상속:** 기존 클래스를 새로운 클래스가 물려받아 사용하거나 확장할 수 있습니다. 이를 통해 코드의 계층 구조를 만들고, 공통 기능을 공유하며 새로운 기능을 추가할 수 있습니다.\n", + "* **객체 지향 프로그래밍의 기반:** 객체 지향 프로그래밍은 현실 세계의 객체들을 모델링하는 데 적합하며, 클래스는 이러한 객체들을 구현하는 기본 단위입니다.\n", + "\n", + "**예시:**\n", + "\n", + "다음은 간단한 \"자동차\" 클래스 예시입니다.\n", + "\n", + "```java\n", + "public class Car {\n", + " // 데이터 멤버 (속성)\n", + " private String brand;\n", + " private int year;\n", + " private double mileage;\n", + "\n", + " // 생성자\n", + " public Car(String brand, int year, double mileage) {\n", + " this.brand = brand;\n", + " this.year = year;\n", + " this.mileage = mileage;\n", + " }\n", + "\n", + " // 메서드 (함수)\n", + " public void startEngine() {\n", + " System.out.println(\"엔진이 시작됩니다.\");\n", + " }\n", + "\n", + " public void drive(double distance) {\n", + " System.out.println(\"주행 중입니다 (\" + distance + \"km)\");\n", + " mileage += distance;\n", + " }\n", + "\n", + " // getters 및 setters (데이터 접근 및 수정)\n", + " public String getBrand() {\n", + " return brand;\n", + " }\n", + "\n", + " public void setBrand(String brand) {\n", + " this.brand = brand;\n", + " }\n", + "\n", + " // ... 다른 메서드들을 추가할 수 있습니다\n", + "}\n", + "```\n", + "\n", + "이 클래스는 `Car` 객체를 생성하고, 그 객체들이 가지는 속성과 기능을 정의합니다. 예를 들어, `new Car(\"토요타\", 2022, 15000)` 을 통해 새로운 `Car` 객체를 만들고, `carObject.startEngine()` 와 `carObject.drive(50)` 와 같은 메서드를 호출하여 객체의 동작을 제어할 수 있습니다.\n" + ] + } + ], + "source": [ + "# lg 버전\n", + "\n", + "chain = prompt | exaone_llm | parser\n", + "\n", + "results = chain.batch([\n", + " { \"role\" : '보안', \"question\" : \"XSS란?\"},\n", + " { \"role\" : '파이썬', \"question\" : \"리스트란?\"},\n", + " { \"role\" : '파이썬', \"question\" : \"딕셔너리란?\"},\n", + " { \"role\" : '자바', \"question\" : \"클래스란?\"},\n", + "\n", + "])\n", + "\n", + "for result in results:\n", + " print(result)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "11081d6d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "안녕하세요, 보안 전문가입니다. 질문하신 **XSS(Cross-Site Scripting, 크로스 사이트 스크립팅)** 에 대해 정리해 드리겠습니다.\n", + "\n", + "### 1. XSS 란 무엇인가요?\n", + "XSS 는 웹사이트에서 악성 스크립트 (일반적으로 JavaScript) 를 외부 사용자가 제어하여 실행하게 하는 취약점을 뜻합니다. 이는 브라우저가 해당 사이트의 데이터에 반응할 때 공격자가 삽입한 스크립트가 실행되어 사용자가 피해를 입게 만듭니다.\n", + "\n", + "### 2. 주요 위험성\n", + "* **피싱 (Phishing):** 공격자가 위장한 사이트에서 사용자의 로그인 정보를 탈취합니다.\n", + "* **세션 토큰 탈취:** 사용자의 세션 ID, 쿠키 등을 훔쳐 보안 땜을 무력화합니다.\n", + "* **Malware 배포:** 사용자 브라우저에 악성 코드를 전달합니다.\n", + "\n", + "### 3. XSS 의 주요 유형\n", + "1. **Reflected XSS (반사형 XSS):**\n", + " * 사용자가 특정 URL 을 클릭하면 서버가 그 URL 을 요청에 담아 페이지에 반영하여 실행됩니다.\n", + " * *예시:* `https://example.com?search=script.js`\n", + "2. **Stored XSS (저장형 XSS):**\n", + " * 서버에 데이터를 저장하는 과정에서 악성 스크립트가 저장되며, 다른 사용자가 해당 데이터를 읽을 때 실행됩니다. (예: 댓글, 블로그 작성)\n", + "3. **DOM-based XSS (DOM 기반 XSS):**\n", + " * 서버 코드보다는 브라우저의 DOM(Manage Document Object Model) 을 조작하여 스크립트를 실행하는 방식입니다.\n", + "\n", + "### 4. 취약점 원인\n", + "* **입력 데이터 검증 부재:** 서버나 클라이언트에서 사용자의 입력 데이터를 정적적으로 필터링하지 않고 직접 렌더링할 경우.\n", + "* **코드 인젝션:** JavaScript 로 입력 데이터를 직접 사용하거나 코딩할 때.\n", + "\n", + "### 5. 방어 및 개선 사항\n", + "1. **Content Security Policy (CSP):**\n", + " * 브라우저가 외부 스크립트 실행을 제한하는 보안 정책입니다.\n", + "2. **입력 데이터 검증 및 엔코딩:**\n", + " * 서버와 클라이언트 모두에서 입력 데이터를 엄격하게 검증하여, 안전한 문자열로 렌더링합니다.\n", + "3. **HTTP Context:**\n", + " * XSS 취약점은 주로 HTTP Context 를 통해 발생합니다. 이를 고려한 안전한 코딩 관행이 필수적입니다.\n", + "\n", + "이러한 보안 관행은 웹 애플리케이션의 안전성을 보장하는 데 핵심적이므로, 개발 및 운영 단계에서 이러한 고려 사항을 반드시 적용하시기 바랍니다.\n", + "안녕하세요, 파이썬 전문가입니다. 질문하신 **\"리스트 (List)\"** 에 대해 핵심적인 내용을 정리해 드리겠습니다.\n", + "\n", + "파이썬에서 **리스트 (List)** 는 데이터를 저장하고 다루기 위한 가장 기본적이고 중요한 데이터 구조 중 하나입니다.\n", + "\n", + "---\n", + "\n", + "### 1. 정의\n", + "리스트는 **오른쪽에서 왼쪽으로 순서를 유지하면서, 여러 개의 요소를 묶어 담을 수 있는 자료형**입니다.\n", + "* **Ordered (순서 유지):** 삽입 순서대로 요소들을 저장합니다. 첫 번째 요소를 찾고 싶으면 0 번째부터 검색합니다.\n", + "* **Mutable (변경 가능):** 일단 생성한 리스트의 크기를 늘리거나, 내용물을 수정할 수 있습니다. (이 점이 튜플과 가장 큰 차이입니다)\n", + "* **Homogeneous or Heterogeneous:** 요소를 담는 데이터 타입이 모두 같아야 하는 것은 아닙니다. (문자열, 정수, 다른 리스트 등 종류를 섞어 담을 수 있습니다)\n", + "\n", + "### 2. 작성 방식 (Syntax)\n", + "중괄호 `[]`를 사용하여 정의합니다.\n", + "\n", + "```python\n", + "# 빈 리스트\n", + "my_list = []\n", + "\n", + "# 요소 추가\n", + "my_list = [1, 'hello', 3.14]\n", + "\n", + "# 요소 확인 (확인만 해보고 싶을 때)\n", + "my_list = list(enumerate([1, 2, 3])) # list로 감싸면 원형 데이터 (list) 로 확인 가능\n", + "```\n", + "\n", + "### 3. 주요 특징 및 동작\n", + "1. **인덱싱 (Indexing):** 첫 번째 요소는 `0` 번 인덱스에서 접근합니다.\n", + " ```python\n", + " first_item = my_list[0]\n", + " last_item = my_list[-1] # 마지막 요소\n", + " ```\n", + "2. **슬라이싱 (Slicing):** 일부분만 추출할 수 있습니다.\n", + " ```python\n", + " # 1 번과 3 번 요소만 추출\n", + " middle = my_list[1:3]\n", + " ```\n", + "3. **변경 방법:**\n", + " ```python\n", + " # 마지막 요소 추가\n", + " my_list.append(4)\n", + " \n", + " # 여러 요소 추가\n", + " my_list.extend([5, 6])\n", + " \n", + " # 특정 요소 삭제\n", + " my_list.pop(1) # 인덱스 1 의 요소 삭제\n", + " my_list.remove(5) # 값 5 가 있는 요소 삭제\n", + " ```\n", + "\n", + "### 4. 리스트 vs 튜플 (List vs Tuple)\n", + "파이썬에서 리스트와 튜플은 둘 다 목록 (Collection) 을 표현할 수 있지만, 사용 목적과 성격이 다릅니다.\n", + "\n", + "| 특징 | 리스트 (List) | 튜플 (Tuple) |\n", + "| :--- | :--- | :--- |\n", + "| **변경성** | **변경 가능** (추가, 수정, 삭제) | **불변** (추가, 수정, 삭제 불가) |\n", + "| **생성자** | `[1, 2, 3]` | `(1, 2, 3)` |\n", + "| **사용처** | 임시 데이터, 반복적으로 수정할 데이터 | 고정된 데이터, 해시 키 사용 시 (Key), 불변성 필요 시 |\n", + "\n", + "### 5. 활용 예시 (복잡한 리스트 활용)\n", + "리스트는 중첩되어 사용하기도 합니다 (예: 학생들의 점수, 여러 행의 데이터 등).\n", + "\n", + "```python\n", + "# 행 (학생 1 점수)\n", + "scores = [90, 85, 80]\n", + "\n", + "# 전체 데이터 (여러 학생의 점수)\n", + "students = [\n", + " [90, 85, 80], \n", + " [70, 75, 70], \n", + " [95, 85, 90]\n", + "]\n", + "\n", + "# 전체 점수 구하기\n", + "average_score = sum(sum(row) for row in students) / len(students)\n", + "```\n", + "\n", + "---\n", + "\n", + "**결론적으로,** 리스트는 **파이썬에서 가장 유연하게 데이터를 관리할 수 있는 구조**이므로, 거의 모든 상황에서 리스트를 기본으로 사용하는 것이 좋습니다.\n", + "\n", + "더 복잡한 데이터 구조나 리스트의 성능, 메모리 관리에 대한 깊은 내용을 필요로하신 경우, 말씀해 주세요.\n", + "파이썬 (Python) 전문가로서 **딕셔너리 (Dictionary)**에 대해 설명해 드리겠습니다.\n", + "\n", + "### 1. 딕셔너리의 정의\n", + "**딕셔너리**는 **'키 (Key)'와 '값 (Value)' 쌍**으로 구성된 데이터를 저장하는 자료형입니다. 각 키는 고유 (unique) 하게 되어 있고, 이를 통해 값을 직접적으로 찾을 수 있습니다.\n", + "\n", + "일반적인 데이터 구조와 비교하자면:\n", + "* **리스트 (List):** 순차적 저장 (인덱스로 접근)\n", + "* **딕셔너리 (Dict):** 키-값 매핑 저장 (키로 검색)\n", + "\n", + "### 2. Python 의 `dict` 구조\n", + "파이썬에서 딕셔너리는 대괄호 `{}` 로 표현되며, 내부적으로는 해시 테이블 (Hash Table) 을 사용해서 매우 빠른 검색 속도를 제공합니다.\n", + "\n", + "**기본 생성 방법:**\n", + "```python\n", + "# 빈 딕셔너리 생성\n", + "empty_dict = {}\n", + "\n", + "# 키와 값을 설정하여 생성\n", + "my_dict = {'name': 'Alex', 'age': 30, 'city': 'Seoul'}\n", + "\n", + "# 여러 줄에서 정의\n", + "my_dict = {'id': 1, 'user': 'admin'} | {'status': 'active'} # (Python 3.9+)\n", + "# 또는\n", + "my_dict = {'id': 1, 'user': 'admin', **{'status': 'active'}}\n", + "```\n", + "\n", + "### 3. 핵심 특징 및 규칙\n", + "1. **키 (Key) 의 제약 조건:**\n", + " * **유일성:** 같은 키는 오직 하나만 존재할 수 있다.\n", + " * **해시 가능 (Hashable) 하여야 한다:** 정수 (`int`), 문자열 (`str`), 튜플 (`tuple`) 등이 가능하나, 리스트 (`list`), 딕셔너리 (`dict`), 집합 (`set`) 은 **변경**될 수 있기 때문에 키로 사용 불가 (변수값이 바뀌면 해시값이 달라져 저장 위치를 찾아낼 수 없으므로).\n", + " * **불변성:** 키는 생성 후 변경할 수 없다.\n", + "2. **값 (Value):**\n", + " * 어떠한 타입이어도 될 수 있다 (수학, 문자, 객체 등).\n", + " * 중복이 허용된다.\n", + "\n", + "### 4. 일반적인 동작 방법\n", + "```python\n", + "# 초기화\n", + "scores = {'Alice': 90, 'Bob': 85, 'Charlie': 95}\n", + "\n", + "# 1. 요소 접근 (Index 사용 X)\n", + "score = scores['Alice']\n", + "print(score) # 90\n", + "\n", + "# 2. 안전 접근 (Key 없음 시 기본값 반환)\n", + "score = scores.get('Charlie')\n", + "print(score) # 95\n", + "score_no_key = scores.get('David') # None 반환\n", + "print(score_no_key)\n", + "\n", + "# 3. 키 확인\n", + "if 'Alice' in scores:\n", + " print('존재합니다.')\n", + "\n", + "# 4. 키를 추가 / 변경\n", + "scores['Eve'] = 80\n", + "scores['Alice'] = 98 # 기존 값 변경\n", + "\n", + "# 5. 키 삭제\n", + "del scores['Charlie']\n", + "# scores.pop('Charlie')\n", + "\n", + "# 6. 반복\n", + "for name, score in scores.items():\n", + " print(f\"{name}: {score}\")\n", + "```\n", + "\n", + "### 5. 왜 딕셔너리를 쓰나요? (활용 사례)\n", + "* **데이터 매핑:** `{'url': 'https://...', 'method': 'POST'}` 같은 설정 정보 저장\n", + "* **검색 최적화:** 이름, 전화번호와 같은 데이터를 빠르게 찾기 위해\n", + "* **문자열 처리:** JSON 파싱이나 데이터 분석 시 가장 일반적인 자료형\n", + "* **문법:** `if condition:` 의 대안으로 `dict.get()` 를 사용하여 안전한 코드 작성\n", + "\n", + "### 요약\n", + "**파이썬의 딕셔너리는 `key` 로 `value` 를 찾을 수 있는 데이터 저장통 (데이터베이스의 단순화된 버전) 입니다.** `key` 는 변하지 않는 고정된 값을, `value` 는 상황에 따라 다양한 타입의 데이터를 저장할 수 있습니다.\n", + "\n", + "이해가 되셨나요? 궁금한 점이 있으면 추가로 물어봐 주세요.\n", + "# 클래스 (Class) 란?\n", + "\n", + "자바에서 **클래스 (Class)** 는 객체를 만들기 위한 **템플릿 (양식/본)**이라고 할 수 있습니다.\n", + "\n", + "## 핵심 개념\n", + "\n", + "| 구분 | 설명 |\n", + "|------|------|\n", + "| **정의** | 특정 특성을 가진 여러 객체를 만들 수 있는 설계도 |\n", + "| **역할** | 데이터 (변수) 와 동작 (메서드) 을 정의함 |\n", + "| **객체 (Object)** | 실제 만들어진 실체 |\n", + "\n", + "## 간단한 예시\n", + "\n", + "```java\n", + "// Dog 클래스 (템플릿)\n", + "class Dog {\n", + " // 변수 (데이터)\n", + " private String name;\n", + " private int age;\n", + " \n", + " // 방법 (동작)\n", + " void bark() {\n", + " System.out.println(\"멍멍!\");\n", + " }\n", + "}\n", + "\n", + "// 객체 생성\n", + "Dog myDog = new Dog();\n", + "myDog.name = \"로보\";\n", + "myDog.age = 3;\n", + "myDog.bark();\n", + "```\n", + "\n", + "## 핵심 요약\n", + "\n", + "- **클래스 = 설계도** → **객체 = 실제 제품**\n", + "- 클래스가 없으면 객체를 만들 수 없음\n", + "- 자바는 \"클래스 중심\"언어가 아니라 \"객체 중심\"언어\n", + "\n", + "클래스는 자바에서 가장 중요한 개념으로, 모든 자바 프로그램은 결국 클래스에 의존하여 실행됩니다. 🚀\n" + ] + } + ], + "source": [ + "# 알리바바 버전\n", + "\n", + "chain = prompt | qwen_llm | parser\n", + "\n", + "results = chain.batch([\n", + " { \"role\" : '보안', \"question\" : \"XSS란?\"},\n", + " { \"role\" : '파이썬', \"question\" : \"리스트란?\"},\n", + " { \"role\" : '파이썬', \"question\" : \"딕셔너리란?\"},\n", + " { \"role\" : '자바', \"question\" : \"클래스란?\"},\n", + "\n", + "])\n", + "\n", + "for result in results:\n", + " print(result)" + ] + }, + { + "cell_type": "markdown", + "id": "19fcf312", + "metadata": {}, + "source": [ + "# 출력 파서\n", + "- StrOutputParser\n", + "- JsonoutputParser\n", + "- PydanticOutputParser" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "205ad8e8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "머신러닝은 인공지능의 한 분야로, 컴퓨터가 데이터를 통해 학습하고 경험을 통해 개선되는 알고리즘을 개발하는 기술입니다.\n", + "{'sentiment': 'positive', 'score': 0.95}\n", + "positive\n", + "0.95\n" + ] + } + ], + "source": [ + "# StrOutputParser\n", + "str_chain = ChatPromptTemplate.from_template(\"{topic}을 한 문장으로 설명해줘\") | watson_llm | parser\n", + "result = str_chain.invoke({\"topic\":\"머신러닝\"})\n", + "print(result)\n", + "\n", + "# JsonoutputParser\n", + "json_chain = ChatPromptTemplate.from_messages([\n", + " ('system', 'json 형식으로만 응답하세요.'),\n", + " ('human', '{text}의 감정을 분석해서 {{\"sentiment\": \"...\", \"score\":0.0}} 형태로'),\n", + "]) | watson_llm | JsonOutputParser()\n", + "result = json_chain.invoke({\"text\":\"오늘 정말 행복한 하루였어요!!\"})\n", + "print(result)\n", + "print(result['sentiment']) # result로 통일\n", + "print(result['score']) # result로 통일" + ] + }, + { + "cell_type": "markdown", + "id": "299dbfa9", + "metadata": {}, + "source": [ + "- PydanticOutputParser\n", + " - 반환타입 : 객체\n", + " - 입력데이터 타입검증, 타입 자동 변환\n", + " - 에러 메시지가 정확하게 나옴\n", + " - 코드가 간결해짐\n", + " - FastAPI 완벽한 호환\n", + " - Json 변환이 쉬움" + ] + }, + { + "cell_type": "code", + "execution_count": 54, + "id": "23dc20f0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "name='홍길동' age=20\n", + "\n" + ] + } + ], + "source": [ + "class User(BaseModel):\n", + " name:str\n", + " age:int = Field(gt=0) # > ge : >=, lt: <, le: <=\n", + "\n", + "# 객체 생성\n", + "user = User(name=\"홍길동\", age='20')\n", + "print(user)\n", + "print(type(user.age))" + ] + }, + { + "cell_type": "code", + "execution_count": 55, + "id": "32efc989", + "metadata": {}, + "outputs": [], + "source": [ + "# user = User(name=\"홍길동\", age='스무살')\n", + "# user = User(name=\"홍길동\", age='0')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "id": "72fe4350", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "negative\n", + "0.9\n", + "['최악', '잘못됐어요', '하루']\n", + "텍스트에서 '최악의 하루'와 '모든 게 잘못됐어요'와 같은 부정적인 표현이 사용되어 부정적인 감정이 드러납니다.\n" + ] + } + ], + "source": [ + "# 감정, 점수, 이유, 키워드 3개\n", + "# Pydantic 모델 정의\n", + "\n", + "class SentimentResult(BaseModel):\n", + " sentiment:Literal['positive', 'negative', 'neutral']\n", + " score:float = Field(ge=0.0, le=1.0, description=\"감정 강도\")\n", + " reason:str = Field(description=\"판단 근거 한 문장\")\n", + " keywords:list[str] = Field(description=\"핵심 키워드 3개 이내\")\n", + "\n", + "# 파서 정의\n", + "pydantic_parser = PydanticOutputParser(pydantic_object=SentimentResult)\n", + "\n", + "# 프롬프트 생성\n", + "#partial(~~~~) : pydantic_parser의 필드를 참고해서 작성해줘\n", + "prompt = ChatPromptTemplate.from_messages([\n", + " ('system', '감정 분석 전문가입니다.\\n\\n {format_instructions}'),\n", + " ('human', '다음 텍스트의 감정을 분석하세요\\n {text}'),\n", + "]).partial(format_instructions=pydantic_parser.get_format_instructions())\n", + "\n", + "chain = prompt | watson_llm | pydantic_parser\n", + "\n", + "result = chain.invoke({\"text\" : \"오늘 최악의 하루였습니다. 모든 게 잘못됐어요.\"})\n", + "\n", + "print(type(result))\n", + "print(result.sentiment)\n", + "print(result.score)\n", + "print(result.keywords)\n", + "print(result.reason)" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "id": "8c9b1505", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "negative\n", + "0.85\n", + "['악몽', '잘못됨', '실패']\n", + "사용자가 '최악의 하루', '모든 게 잘못됐어요'와 같은 부정적인 표현을 사용하여 강한 부정 감정을 나타냈습니다.\n" + ] + } + ], + "source": [ + "chain = prompt | exaone_llm | pydantic_parser\n", + "\n", + "result = chain.invoke({\"text\" : \"오늘 최악의 하루였습니다. 모든 게 잘못됐어요.\"})\n", + "\n", + "print(type(result))\n", + "print(result.sentiment)\n", + "print(result.score)\n", + "print(result.keywords)\n", + "print(result.reason)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df0128dc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "=== 감정 분석 결과 ===\n", + "😡[negative] 0.90\n", + " 입력 : 이 제품 정말 별로에요. 돈 낭비였습니다.....\n", + " 이유 : 텍스트에 이 제품에 대한 부정적인 평가와 돈 낭비의 느낌이 표현되어 있습니다.\n", + "😑[neutral ] 0.00\n", + " 입력 : 그냥 평범한 하루였어요. 더 특별한 건 없었어요.....\n", + " 이유 : 텍스트에는 특별히 긍정적이거나 부정적인 감정이 표현되지 않았습니다. 평범하고 특별하지 않은 하루를 설명하고 있습니다.\n", + "😊[positive] 0.90\n", + " 입력 : 와, 생각보다 훨씬 맛있었어요! 강력 추천합니다......\n", + " 이유 : 긍정적인 표현인 '와', '생각보다 훨씬 맛있었어요', '강력 추천합니다'가 사용되었기 때문\n", + "😡[negative] 0.75\n", + " 입력 : 서비스가 너무 불친절하고 음식도 늦게 나왔어요.....\n", + " 이유 : 텍스트에서 '불친절한 서비스'와 '늦게 나온 음식'이라는 부정적인 표현이 나타나 감정이 부정적인 것으로 판단됩니다.\n", + "😡[negative] 0.60\n", + " 입력 : 아 벌써 배고파요 ㅈ댔어요....\n", + " 이유 : 식사를 했다는 언급과 함께 아직 배고픔을 호소하는 반복적인 표현이 나왔기 때문에, 약간 부정적인 감정이 담겨 있는 것으로 판단됩니다.\n" + ] + } + ], + "source": [ + "texts = [\n", + " \"이 제품 정말 별로에요. 돈 낭비였습니다.\",\n", + " \"그냥 평범한 하루였어요. 더 특별한 건 없었어요.\",\n", + " \"와, 생각보다 훨씬 맛있었어요! 강력 추천합니다..\",\n", + " \"서비스가 너무 불친절하고 음식도 늦게 나왔어요.\",\n", + " \"아 벌써 배고파요 ㅈ댔어요\",\n", + "]\n", + "\n", + "chain = prompt | watson_llm | pydantic_parser\n", + "\n", + "results = chain.batch([{\"text\": t} for t in texts])\n", + "\n", + "print(\"=== 감정 분석 결과 ===\")\n", + "for text, r in zip(texts, results):\n", + " bar = ' ' * int(r.score * 10) + ' ' * (10 - int(r.score * 10))\n", + " emoji = {'positive' : '😊', 'negative' : '😡', 'neutral' : '😑'}[r.sentiment]\n", + " print(f'{emoji}[{r.sentiment:8s}] {bar} {r.score:.2f}')\n", + " print(f' 입력 : {text[:30]}....')\n", + " print(f' 이유 : {r.reason}')" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "id": "77aeeeb8", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "negative\n", + "0.7\n", + "제품 포장이 허술하여 만족도가 떨어집니다.\n", + "카테고리 : product, 조치 : 제품 포장 개선 필요\n" + ] + } + ], + "source": [ + "class AdvencedSentiment(BaseModel):\n", + " sentiment:Literal['positive', 'negative', 'neutral']\n", + " score:float = Field(ge=0.0, le=1.0, description=\"감정 강도\")\n", + " category:Literal['product', 'serivce', 'food', 'general'] = Field(description=\"판단 근거 한 문장\")\n", + " summary:str = Field(description=\"한 줄 요약\")\n", + " action:str = Field(description=\"비즈니스 조치 방향\")\n", + "\n", + "# 파서 정의\n", + "pydantic_parser = PydanticOutputParser(pydantic_object=AdvencedSentiment)\n", + "\n", + "# 프롬프트 생성\n", + "#partial(~~~~) : pydantic_parser의 필드를 참고해서 작성해줘\n", + "prompt = ChatPromptTemplate.from_messages([\n", + " ('system', '당신은 cx(고객경험) 분석가입니다.\\n\\n {format_instructions}'),\n", + " ('human', '{text}'),\n", + "]).partial(format_instructions=pydantic_parser.get_format_instructions())\n", + "\n", + "chain = prompt | watson_llm | pydantic_parser\n", + "\n", + "result = chain.invoke({\"text\" : \"배소은 빠른데 포장이 너무 허술해요.\"})\n", + "\n", + "print(result.sentiment)\n", + "print(result.score)\n", + "print(result.summary)\n", + "print(f'카테고리 : {result.category}, 조치 : {result.action}')" + ] + }, + { + "cell_type": "markdown", + "id": "55145757", + "metadata": {}, + "source": [ + "#### RunnableLambda\n", + "- chain => RunnableSequence 생성하기 때문에 일반 파이썬 함수는 바로 연결 불가\n", + "- 일반 함수를 감싸는 용도로 사용" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "50931351", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "안녕하세요. 언어 전문가로서 파이썬(PYTHON)에 대해 자세하고 체계적으로 설명해 드리겠습니다.\n", + "\n", + "파이썬은 현재 전 세계적으로 가장 인기 있고 널리 사용되는 프로그래밍 언어 중 하나이며, 그 인기는 매우 명확한 이유가 있습니다. 파이썬이 무엇인지, 어떤 특징을 가지며, 어디에 사용되는지를 중심으로 설명드리겠습니다.\n", + "\n", + "---\n", + "\n", + "## 1. 파이썬이란 무엇인가? (WHAT IS PYTHON?)\n", + "\n", + "파이썬은 **고급(HIGH-LEVEL), 해석형(INTERPRETED), 범용 프로그래밍 언어**입니다.\n", + "\n", + "* **고급 언어 (HIGH-LEVEL):** 인간의 자연어(영어)와 매우 유사하여 배우고 사용하기가 쉽습니다. 복잡한 시스템 레벨의 세부 사항을 직접 다룰 필요 없이, 원하는 기능을 구현하는 데 집중할 수 있습니다.\n", + "* **해석형 언어 (INTERPRETED):** 코드를 한 줄씩 읽어 실행하는 방식입니다. (컴파일 과정이 필요 없어 개발 속도가 빠르고 디버깅이 용이합니다.)\n", + "* **범용 언어 (GENERAL-PURPOSE):** 특정 분야에만 국한되지 않고, 웹 개발, 데이터 분석, 인공지능, 시스템 자동화 등 거의 모든 분야에서 활용될 수 있습니다.\n", + "\n", + "## 2. 파이썬의 핵심 특징 (KEY FEATURES)\n", + "\n", + "파이썬이 전 세계적으로 사랑받는 이유는 다음과 같은 강력한 특징들 때문입니다.\n", + "\n", + "### ① 쉬운 문법과 가독성 (READABILITY AND SIMPLICITY)\n", + "파이썬의 가장 큰 장점은 **문법이 간결하고 읽기 쉽다**는 점입니다. 다른 언어들에 비해 코드가 마치 영어 문장처럼 직관적이기 때문에 초보자가 쉽게 접근할 수 있으며, 팀원들이 코드를 빠르게 이해하고 협업하기가 매우 용이합니다.\n", + "\n", + "### ② 동적 타입 언어 (DYNAMICALLY TYPED)\n", + "변수의 타입을 미리 선언할 필요 없이, 값이 할당될 때 타입이 자동으로 결정됩니다. 이로 인해 코드를 작성하는 속도가 빨라지고 유연성이 높아집니다.\n", + "\n", + "### ③ 방대한 라이브러리 생태계 (VAST ECOSYSTEM AND LIBRARIES)\n", + "파이썬의 강력함은 그 뒤를 잇는 거대한 라이브러리(모듈) 생태계에서 나옵니다. 이미 수많은 개발자들이 만들어 놓은 라이브러리(예: NUMPY, PANDAS, TENSORFLOW 등)를 가져와서 복잡한 기능을 단 몇 줄의 코드로 구현할 수 있습니다.\n", + "\n", + "### ④ 방대한 커뮤니티 (LARGE COMMUNITY)\n", + "사용자가 많기 때문에 문제 발생 시 해결책을 찾기 쉽고, 온라인 자료, 튜토리얼, 커뮤니티 지원이 매우 활발합니다.\n", + "\n", + "## 3. 파이썬의 주요 활용 분야 (APPLICATIONS)\n", + "\n", + "파이썬은 그 범용성 덕분에 현재 거의 모든 첨단 기술 분야에서 핵심적인 역할을 수행하고 있습니다.\n", + "\n", + "| 분야 | 주요 활용 내용 | 대표 라이브러리/프레임워크 |\n", + "| :--- | :--- | :--- |\n", + "| **데이터 과학 (DATA SCIENCE)** | 대규모 데이터 처리, 통계 분석, 데이터 시각화 | PANDAS, NUMPY, MATPLOTLIB, SCIPY |\n", + "| **인공지능 및 머신러닝 (AI/ML)** | 딥러닝 모델 구축, 예측 모델 개발, 자연어 처리 | TENSORFLOW, PYTORCH, SCIKIT-LEARN |\n", + "| **웹 개발 (WEB DEVELOPMENT)** | 백엔드 로직 구현, 서버 관리, API 개발 | DJANGO, FLASK |\n", + "| **업무 자동화 (AUTOMATION)** | 반복적인 파일 정리, 이메일 발송, 시스템 관리 등 단순 반복 작업 자동화 | OS, SELENIUM, OPENPYXL |\n", + "| **사물 인터넷 (IOT)** | 센서 데이터 수집 및 분석, 장치 제어 | (다양한 API 연동) |\n", + "| **스크립팅 (SCRIPTING)** | 시스템 관리, 쉘 스크립트 대체, 간단한 프로그램 작성 | |\n", + "\n", + "## 4. 파이썬을 시작할 때의 조언\n", + "\n", + "파이썬을 처음 시작하신다면 다음과 같은 순서를 추천드립니다.\n", + "\n", + "1. **기초 문법 학습:** 변수, 자료형(리스트, 딕셔너리), 조건문, 반복문, 함수 등 기본적인 문법을 확실히 익힙니다.\n", + "2. **문제 해결 연습:** 간단한 알고리즘 문제(예: 백준, LEETCODE 등)를 풀어보면서 논리적 사고력과 코딩 능력을 향상시킵니다.\n", + "3. **특정 분야 선택:** 관심 있는 분야(데이터 분석, 웹 개발 등)를 정하고, 해당 분야의 라이브러리(예: PANDAS)를 사용하여 실제 프로젝트를 진행하며 실력을 심화합니다.\n", + "\n", + "---\n", + "\n", + "### 요약 정리\n", + "\n", + "파이썬은 **배우기 쉽고, 강력하며, 다재다능한** 프로그래밍 언어입니다. 간결한 문법 덕분에 개발자는 복잡한 코드 작성에 시간을 낭비하지 않고, **실제 문제 해결과 혁신적인 아이디어를 구현하는 데 집중**할 수 있게 해줍니다.\n", + "\n", + "궁금한 특정 분야(예: 파이썬 문법, 데이터 분석 라이브러리 등)가 있다면 언제든지 다시 질문해 주십시오. 자세히 설명해 드리겠습니다!\n" + ] + } + ], + "source": [ + "def upper(text):\n", + " return text.upper()\n", + "\n", + "prompt = ChatPromptTemplate.from_messages([\n", + " (\"system\", \"당신은 언어 전문가입니다.\"),\n", + " (\"human\", \"{topic}에 대해 설명해줘\"),\n", + "\n", + "])\n", + "\n", + "chain = prompt | gemma_llm | StrOutputParser() | RunnableLambda(upper)\n", + "\n", + "print(chain.invoke({\"topic\" : \"python\"}))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bc8589a0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "파이썬에서 **리스트(List)**는 가장 기본적이고, 가장 많이 사용되는 자료구조 중 하나입니다. 리스트는 여러 개의 데이터를 순서대로 저장할 수 있는 **순서가 있는(Ordered)**, **변경 가능한(Mutable)** 컬렉션입니다. 리스트에 대해 자세히 설명하고, 사용법과 특징, 그리고 주요 메서드에 대해 알려드리겠습니다. --- ## 1. 리스트(List)의 기본 이해 ### 📚 핵심 특징 | 특징 | 설명 | | :--- | :--- | | **순서 O (Ordered)** | 리스트에 저장된 항목들은 입력된 순서대로 순서가 유지됩니다. 인덱스를 통해 특정 위치의 항목에 접근할 수 있습니다. | | **변경 가능 O (Mutable)** | 리스트를 생성한 후에도 항목을 추가, 삭제, 수정할 수 있습니다. (다른 자료구조인 튜플(Tuple)과 구별되는 가장 큰 특징입니다.) | | **중복 허용 O (Allows Duplicates)** | 동일한 값을 여러 번 저장할 수 있습니다. | | **다양한 자료형 가능** | 리스트 안에는 숫자(정수, 실수), 문자열, 다른 리스트 등 모든 종류의 데이터가 혼합되어 저장될 수 있습니다. | ### 📝 리스트의 표현 리스트는 **대괄호 `[ ]`**를 사용하여 각 항목을 쉼표(`,`)로 구분하여 나열합니다. ```python # 정수들이 포함된 리스트 numbers = [1, 5, 10, 15, 20] # 문자열들이 포함된 리스트 fruits = [\"apple\", \"banana\", \"cherry\"] # 다양한 자료형이 혼합된 리스트 mixed_list = [10, \"hello\", 3.14, True] ``` --- ## 2. 리스트 사용법 (핵심 연산) ### 1. 항목 접근 (Indexing) 리스트의 각 항목은 **인덱스(Index)**라는 순서 번호를 가집니다. 파이썬은 **0부터 시작**합니다. | 위치 | 0 | 1 | 2 | 3 | 4 | | :--- | :--- | :--- | :--- | :--- | :--- | | 값 | 1 | 5 | 10 | 15 | 20 | ```python my_list = [\"A\", \"B\", \"C\", \"D\", \"E\"] # 첫 번째 항목 접근 (인덱스 0) print(my_list[0]) # 결과: A # 세 번째 항목 접근 (인덱스 2) print(my_list[2]) # 결과: C # 음수 인덱싱을 사용하여 뒤에서부터 접근 (마지막 항목은 -1) print(my_list[-1]) # 결과: E (마지막 항목) ``` ### 2. 항목 수정 (Modification) 리스트가 변경 가능하기 때문에, 인덱스를 사용하여 값을 쉽게 수정할 수 있습니다. ```python fruits = [\"apple\", \"banana\", \"cherry\"] # 인덱스 1의 값을 변경 fruits[1] = \"orange\" print(fruits) # 결과: ['apple', 'orange', 'cherry'] ``` ### 3. 항목 추가 (Adding Elements) 리스트의 크기를 늘리는 방법입니다. | 메서드 | 설명 | 예시 | | :--- | :--- | :--- | | **`.append(값)`** | 리스트의 **맨 끝**에 새로운 항목을 추가합니다. | `fruits.append(\"grape\")` | | **`.insert(인덱스, 값)`** | 특정 인덱스 위치에 값을 삽입합니다. | `fruits.insert(1, \"orange\")` | | **`.extend(다른 리스트)`** | 다른 리스트의 모든 항목을 현재 리스트에 추가합니다. | `fruits.extend([\"kiwi\", \"melon\"])` | ### 4. 항목 제거 (Removing Elements) 리스트에서 항목을 삭제하는 방법입니다. | 메서드 | 설명 | 예시 | | :--- | :--- | :--- | | **`.pop(인덱스)`** | 지정한 인덱스의 항목을 **제거하고 그 값을 반환**합니다. (인덱스를 지정하지 않으면 마지막 항목이 제거됩니다.) | `removed = fruits.pop(0)` | | **`.remove(값)`** | 리스트에서 **해당 값이 처음으로 나타나는 위치의 항목을 제거**합니다. | `fruits.remove(\"banana\")` | | **`del` 키워드** | 특정 인덱스의 항목이나 리스트 자체를 완전히 삭제합니다. | `del fruits[2]` | ### 5. 리스트 정보 확인 | 함수 | 설명 | 예시 | | :--- | :--- | :--- | | **`len(리스트)`** | 리스트에 들어있는 **항목의 총 개수**를 반환합니다. | `len(fruits)` | | **`in` 연산자** | 특정 값이 리스트 안에 존재하는지 확인합니다. | `\"apple\" in fruits` (결과: True) | --- ## 💡 전체 예제 요약 ```python # 1. 리스트 생성 colors = [\"red\", \"green\", \"blue\", \"yellow\"] print(f\"원래 리스트: {colors}\") # 2. 항목 추가 (append 사용) colors.append(\"purple\") print(f\"추가 후: {colors}\") # 3. 항목 수정 (인덱스 사용) colors[1] = \"teal\" # 인덱스 1 ('green')을 'teal'로 변경 print(f\"수정 후: {colors}\") # 4. 항목 제거 (pop 사용) removed_color = colors.pop(0) # 첫 번째 항목 ('red')을 제거하고 반환 print(f\"제거된 항목: {removed_color}\") print(f\"최종 리스트: {colors}\") ``` --- ## 🌟 요약 정리 파이썬 리스트는 데이터의 **순서**를 중요하게 다루며, 데이터를 **자유롭게 수정**할 수 있어 데이터 관리 및 프로그래밍에서 매우 유용합니다. * **기억할 점:** 리스트는 순서가 있으며, `[ ]`로 표현되고, `append()`, `pop()`, `remove()` 등의 메서드를 통해 쉽게 조작할 수 있습니다.\n" + ] + } + ], + "source": [ + "# 후처리 함수\n", + "def remove_newline(text):\n", + " return text.replace(\"\\n\", \" \")\n", + "\n", + "prompt = ChatPromptTemplate.from_template(\"{question}에 대해 답변해줘\")\n", + "\n", + "chain = prompt | gemma_llm | StrOutputParser() | RunnableLambda(remove_newline)\n", + "\n", + "print(chain.invoke({\"question\": \"파이썬의 리스트\"}))" + ] + }, + { + "cell_type": "markdown", + "id": "6a027bda", + "metadata": {}, + "source": [ + "#### RunnablePassThrough\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "999f2ac6", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Q : 파이썬이란?\n", + "A: 파이썬(Python)은 오늘날 전 세계적으로 가장 인기 있고 널리 사용되는 프로그래밍 언어 중 하나입니다.\n", + "\n", + "단순히 하나의 정의로 설명하기보다는, 파이썬이 무엇이고 왜 그렇게 유명한지를 포괄적으로 설명해 드리겠습니다.\n", + "\n", + "---\n", + "\n", + "## 🐍 1. 파이썬이란 무엇인가? (정의)\n", + "\n", + "파이썬은 **고급(High-level) 해석형(Interpreted) 프로그래밍 언어**입니다.\n", + "\n", + "* **고급 언어 (High-level):** 인간이 이해하기 쉬운 자연어(영어)와 유사한 방식으로 코드를 작성할 수 있도록 설계되어, 복잡한 컴퓨터 내부 구조를 몰라도 쉽게 프로그래밍을 시작할 수 있습니다.\n", + "* **해석형 언어 (Interpreted):** 코드를 실행할 때 한 줄씩 즉시 해석하여 실행합니다. (컴파일 과정이 필요 없어 개발 속도가 빠르고 편리합니다.)\n", + "\n", + "쉽게 말해, **파이썬은 사람이 코드를 읽고 이해하기 쉽게 만든 언어**라고 할 수 있습니다.\n", + "\n", + "---\n", + "\n", + "## ✨ 2. 파이썬의 핵심 특징 (왜 파이썬이 인기 있는가?)\n", + "\n", + "파이썬이 다른 언어들 사이에서 압도적인 인기를 얻는 이유는 다음과 같은 핵심적인 장점들 때문입니다.\n", + "\n", + "### 1. 쉬운 문법과 높은 가독성 (Readability)\n", + "파이썬의 가장 큰 장점은 문법이 매우 간결하고 영어와 비슷합니다. 코드가 마치 영어 문장처럼 읽기 쉽기 때문에, 초보자도 비교적 적은 시간 안에 코드를 이해하고 작성할 수 있습니다.\n", + "\n", + "### 2. 방대한 라이브러리와 생태계 (Libraries & Ecosystem)\n", + "파이썬은 수많은 외부 라이브러리(모듈)를 제공합니다. 이는 개발자들이 이미 만들어 놓은 코드(재사용 가능한 도구)를 활용하여 복잡한 기능을 훨씬 빠르게 구현할 수 있게 해줍니다. (예: 데이터 분석을 위한 Pandas, 인공지능을 위한 TensorFlow 등)\n", + "\n", + "### 3. 다용도성 (Versatility)\n", + "파이썬은 특정 분야에만 국한되지 않고, 거의 모든 종류의 프로그래밍 작업에 활용될 수 있습니다. 웹 개발부터 데이터 분석, 인공지능, 게임 개발, 시스템 자동화 등 광범위한 분야에서 사용됩니다.\n", + "\n", + "### 4. 강력한 커뮤니티 (Community)\n", + "전 세계 수많은 개발자들이 파이썬을 사용하고 있으며, 이로 인해 문제 발생 시 도움을 요청하거나 자료를 찾기가 매우 쉽습니다. 공식 문서, 튜토리얼, 온라인 커뮤니티 등이 매우 활성화되어 있습니다.\n", + "\n", + "---\n", + "\n", + "## 💡 3. 파이썬은 어디에 사용되나요? (주요 활용 분야)\n", + "\n", + "파이썬의 다용도성 덕분에 현재 가장 활발하게 사용되는 분야는 다음과 같습니다.\n", + "\n", + "### 1. 데이터 과학 및 분석 (Data Science & Analysis)\n", + "* **설명:** 대규모 데이터를 수집, 처리, 분석하여 의미 있는 통찰력을 얻는 분야입니다.\n", + "* **주요 라이브러리:** NumPy, Pandas, SciPy\n", + "\n", + "### 2. 인공지능 및 머신러닝 (AI & Machine Learning)\n", + "* **설명:** 딥러닝 모델을 구축하고 복잡한 예측 및 분류 알고리즘을 개발하는 데 사용됩니다.\n", + "* **주요 라이브러리:** TensorFlow, PyTorch, Scikit-learn\n", + "\n", + "### 3. 웹 개발 (Web Development)\n", + "* **설명:** 웹사이트의 백엔드(서버 측 로직)를 구축하는 데 사용됩니다.\n", + "* **주요 프레임워크:** Django, Flask\n", + "\n", + "### 4. 자동화 및 스크립팅 (Automation & Scripting)\n", + "* **설명:** 반복적인 작업을 자동화하거나, 파일 관리, 데이터 입력 등의 반복적인 작업을 코드로 처리하여 시간을 절약하는 데 사용됩니다. (예: 파일 이름 일괄 변경, 이메일 자동 발송 등)\n", + "\n", + "### 5. 소프트웨어 테스트 및 QA\n", + "* **설명:** 애플리케이션의 버그를 자동으로 검사하고 테스트하는 스크립트를 작성하는 데 활용됩니다.\n", + "\n", + "---\n", + "\n", + "## 📚 요약 정리\n", + "\n", + "| 구분 | 내용 | 설명 |\n", + "| :--- | :--- | :--- |\n", + "| **언어 종류** | 고급, 해석형 언어 | 사람이 쉽게 이해하고 코드를 바로 실행할 수 있음. |\n", + "| **핵심 장점** | 높은 가독성, 방대한 라이브러리 | 코드를 읽기 쉽고, 이미 만들어진 도구를 쉽게 활용할 수 있음. |\n", + "| **주요 분야** | 데이터 분석, AI/ML, 웹 개발, 자동화 | 거의 모든 IT 분야에서 활용 가능함. |\n", + "| **학습 난이도** | 초보자에게 매우 쉬움 | 프로그래밍을 처음 시작하는 사람에게 가장 적합함. |\n", + "\n", + "**결론적으로, 파이썬은 프로그래밍 입문자에게 최고의 언어이며, 데이터 분석이나 인공지능과 같은 첨단 분야로 진출하고 싶은 사람들에게도 필수적인 도구입니다.**\n" + ] + } + ], + "source": [ + "\n", + "prompt = ChatPromptTemplate.from_template(\"{question}에 대해 답변해줘\")\n", + "\n", + "chain = (\n", + " {\"question\":RunnablePassthrough(), \n", + " \"answer\" : prompt | gemma_llm | StrOutputParser()\n", + " } | RunnableLambda(lambda x:f\"Q : {x['question']}\\nA: {x['answer']}\")\n", + ")\n", + "\n", + "result = chain.invoke(\"파이썬이란?\")\n", + "print(result)" + ] + }, + { + "cell_type": "markdown", + "id": "59be130e", + "metadata": {}, + "source": [ + "#### RunnableParallel\n", + " - 여러 chain을 호출할 때 사용\n", + " - 실제 병렬 처리 성능은 컴퓨터 자원(CPU, GPU, Memory)에 영향을 받음\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6cee6d40", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "요약 인공지능은 인간의 지능을 모방하는 기술입니다.\n", + "키워드 인공지능, 인간 지능, 모방\n" + ] + } + ], + "source": [ + "parser = StrOutputParser()\n", + "# 요약\n", + "summary_chain = ChatPromptTemplate.from_template(\"다음 텍스트를 한 문장으로 요약해줘:{text}\") | gemma_llm | parser\n", + "\n", + "# 키워드 추출\n", + "keyword_chain = ChatPromptTemplate.from_template(\"다음 텍스트의 핵심 키워드 3개를 콤마로 나열해줘:{text}\") | gemma_llm | parser\n", + "\n", + "parallel_chain = RunnableParallel(summary=summary_chain, keyword=keyword_chain)\n", + "result = parallel_chain.invoke(\"{'text' : '인공지능은 인간의 지능을 모방하는 기술리....'}\")\n", + "print(\"요약\", result['summary'])\n", + "print(\"키워드\", result['keyword'])" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "363444633676776e", + "metadata": { + "ExecuteTime": { + "end_time": "2026-05-27T08:14:15.946621639Z", + "start_time": "2026-05-27T08:14:15.938419192Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'summary': '인공지능은 인간의 지능을 모방하는 기술입니다.', 'keyword': '인공지능, 인간 지능, 모방'}\n" + ] + } + ], + "source": [ + "# {\"text\" : LLM 답변}\n", + "analysis_chain = ChatPromptTemplate.from_template(\"다음 리뷰를 분석해줘 : {review}\") | gemma_llm | parser | {\"text\":RunnablePassthrough()}\n", + "\n", + "full_chain = (RunnablePassthrough.assign(summary = ChatPromptTemplate.from_template(\"{review} 한 줄 요약\") | gemma_llm | parser)\n", + ".assign(sentiment = ChatPromptTemplate.from_template(\"{review} 감정 : 긍정/부정/중립 중 하나만\") | gemma_llm | parser))\n", + "\n", + "full_chain.invoke({\"review\":\"정말 맛있는 음식이었어\"})\n", + "print(result)" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "#### 멀티턴 대화\n", + "- LLM : stateless (이전의 대화 내용을 기억 못함)\n", + " - 대화 이력 관리를 위해 messages 리스트에 누적 필요" + ], + "id": "76a62776a85dbfed" + }, + { + "metadata": { + "ExecuteTime": { + "end_time": "2026-05-27T08:51:48.404724378Z", + "start_time": "2026-05-27T08:50:17.953668192Z" + } + }, + "cell_type": "code", + "source": [ + "message = [\n", + " SystemMessage(content=\"당신은 친절한 파이썬 튜어입니다. 한국어로 답변하세요\")\n", + "]\n", + "\n", + "def chat(user_input):\n", + " message.append(HumanMessage(user_input))\n", + " response = gemma_llm.invoke(message)\n", + " message.append(AIMessage(response.content))\n", + " return response.content\n", + "\n", + "\n", + "print(chat(\"파이썬이란?\"))\n", + "print(chat(\"방금 말한 내용의 장점 3가지는?\"))\n", + "print(chat(\"그 중 첫번째 장점에 대한 예시 코드 작성해줘\"))\n", + "print(chat(\"두 번째 장점에 대한 예시 코드 작성해줘\"))\n", + "\n", + "for m in message:\n", + " print(f\"[{m.type}] {m.content[:40]}...\")\n" + ], + "id": "e80798f79d67fe4a", + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "안녕하세요! 만나서 반갑습니다. 저는 여러분의 친절한 파이썬 튜터입니다. 😊\n", + "\n", + "\"파이썬이란 무엇인가요?\"라는 질문은 정말 많은 분들이 궁금해하시는 첫 질문이에요! 아주 쉽게 설명해 드릴게요.\n", + "\n", + "---\n", + "\n", + "### 🐍 파이썬(Python)이란 무엇인가요?\n", + "\n", + "가장 간단하게 정의하자면, **파이썬은 우리가 컴퓨터에게 내릴 명령을 이해하고 실행할 수 있도록 만들어진 '프로그래밍 언어'**입니다.\n", + "\n", + "마치 우리가 한국어나 영어로 소통하듯이, 컴퓨터와 소통하기 위해 파이썬이라는 특별한 문법(규칙)을 사용하는 것이죠.\n", + "\n", + "#### 🌟 파이썬의 가장 큰 특징 3가지\n", + "\n", + "파이썬이 전 세계적으로 가장 인기 있는 언어 중 하나가 된 데는 몇 가지 특별한 이유가 있습니다.\n", + "\n", + "**1. 배우기 쉽다 (Readability & Simplicity)**\n", + "파이썬은 다른 언어들에 비해 문법이 매우 간결하고 사람이 읽기 쉬운 형태로 설계되어 있습니다. 마치 영어 문장처럼 코드를 작성하면 그 의미가 명확해서, 프로그래밍을 처음 시작하는 분들도 비교적 쉽게 배울 수 있습니다.\n", + "\n", + "**2. 다재다능하다 (Versatility)**\n", + "파이썬은 특정 분야에만 국한되지 않고, **거의 모든 분야**에서 활용될 수 있습니다. 데이터 분석, 인공지능(AI), 웹 개발, 게임 개발, 자동화 스크립트 작성 등 무궁무진한 분야에서 사용됩니다.\n", + "\n", + "**3. 방대한 라이브러리 (Massive Libraries)**\n", + "파이썬을 사용하는 엄청난 이유 중 하나는 이미 잘 만들어진 수많은 **라이브러리(모듈)**가 존재한다는 점입니다. 누군가 이미 만들어 놓은 유용한 도구들을 가져와서 아주 쉽게 복잡한 기능을 구현할 수 있습니다. (마치 레고 블록처럼 이미 만들어진 부품들을 조립하는 느낌이랄까요?)\n", + "\n", + "---\n", + "\n", + "### 🛠️ 파이썬은 어디에 사용되나요? (활용 분야)\n", + "\n", + "파이썬의 다재다능함 덕분에 현재 다음과 같은 분야에서 폭발적으로 사용되고 있습니다.\n", + "\n", + "1. **데이터 과학 및 분석 (Data Science & Analysis):**\n", + " * 빅데이터를 처리하고 통계를 분석하는 데 가장 강력합니다. (Pandas, NumPy 라이브러리 활용)\n", + "2. **인공지능 (AI) 및 머신러닝 (Machine Learning):**\n", + " * 현재 AI 분야의 대세입니다. 딥러닝 모델을 만들고 예측하는 데 파이썬이 압도적으로 사용됩니다. (TensorFlow, PyTorch 등)\n", + "3. **웹 개발 (Web Development):**\n", + " * 사용자 인터페이스(웹사이트)를 만들 때 백엔드(서버) 개발에 사용됩니다. (Django, Flask 프레임워크 활용)\n", + "4. **업무 자동화 (Automation & Scripting):**\n", + " * 반복적이고 지루한 컴퓨터 작업을 대신 처리해주는 스크립트를 작성할 때 매우 유용합니다. (파일 정리, 이메일 발송 등)\n", + "5. **소프트웨어 테스트 및 QA:**\n", + " * 소프트웨어의 오류를 찾아내고 테스트하는 작업에도 널리 사용됩니다.\n", + "\n", + "---\n", + "\n", + "### 💡 요약 정리\n", + "\n", + "| 구분 | 설명 | 비유 |\n", + "| :--- | :--- | :--- |\n", + "| **정의** | 사람이 컴퓨터에게 내리는 **프로그래밍 언어** | 컴퓨터와 대화하는 **언어** |\n", + "| **특징** | 문법이 쉽고, 읽기 편하며, 라이브러리가 풍부함 | 레고 블록처럼 쉽게 조립 가능 |\n", + "| **주요 용도** | 데이터 분석, AI/머신러닝, 웹 개발, 자동화 | 다양한 분야의 **만능 도구** |\n", + "\n", + "---\n", + "\n", + "### 🚀 다음 단계는 무엇일까요?\n", + "\n", + "파이썬은 시작하기에 정말 완벽한 언어입니다. 복잡해 보일 수 있지만, 작은 목표부터 시작해서 재미있게 코드를 작성해 나간다면 분명 멋진 결과물을 만들어낼 수 있을 거예요!\n", + "\n", + "혹시 파이썬의 특정 개념(예: 변수, 함수, 클래스 등)에 대해 더 깊이 알고 싶으시거나, 어떤 분야에 관심이 있으신지 말씀해주시면, 제가 그에 맞춰서 더 자세하고 재미있는 학습 방향을 제시해 드릴게요! 😊\n", + "\n", + "**언제든지 궁금한 것을 물어보세요!**\n", + "아, 네! 제가 앞서 설명드렸던 파이썬의 가장 큰 장점 3가지를 다시 정리해서 친절하게 설명해 드릴게요! 😊\n", + "\n", + "파이썬이 전 세계적으로 사랑받는 핵심적인 이유 세 가지입니다.\n", + "\n", + "### 🥇 파이썬의 장점 3가지\n", + "\n", + "#### 1. 배우기 쉽다 (Readability & Simplicity)\n", + "* **설명:** 파이썬은 문법(규칙)이 매우 간결하고 사람이 읽기 쉽게 설계되어 있습니다.\n", + "* **장점:** 프로그래밍을 처음 시작하는 분들도 복잡한 이론에 얽매이지 않고 코드를 빠르게 이해하고 작성할 수 있습니다. 마치 일상 언어처럼 코드를 읽는 것이 쉽다는 것이 가장 큰 장점입니다.\n", + "\n", + "#### 2. 다재다능하다 (Versatility)\n", + "* **설명:** 파이썬은 특정 분야에 갇혀 있지 않고, 거의 모든 종류의 프로그래밍 작업에 활용될 수 있습니다.\n", + "* **장점:** 데이터 분석, 인공지능(AI), 웹 개발, 자동화 스크립트 작성 등 **매우 광범위한 분야**에서 사용이 가능하기 때문에, 원하는 목표에 맞춰 언어를 선택하기가 매우 용이합니다.\n", + "\n", + "#### 3. 방대한 라이브러리 (Massive Libraries)\n", + "* **설명:** 이미 수많은 개발자들이 만들어 놓은 유용한 도구들(라이브러리, 모듈)이 매우 풍부하게 존재합니다.\n", + "* **장점:** 처음부터 모든 것을 만들 필요가 없습니다. 이미 검증된 라이브러리들을 가져와서 원하는 기능을 아주 쉽고 빠르게 구현할 수 있어 개발 속도가 엄청나게 빨라집니다.\n", + "\n", + "---\n", + "\n", + "**요약하자면,** 파이썬은 **\"쉽게 배우면서, 다재다능하게 활용하고, 이미 만들어진 도구들 덕분에 빠르게 결과물을 만들 수 있는\"** 최고의 언어라고 할 수 있습니다!\n", + "\n", + "이 세 가지 장점 때문에 파이썬은 현재 IT 분야에서 가장 강력한 입지를 가지고 있답니다. 궁금한 점이 있다면 언제든지 다시 질문해 주세요! 😊\n", + "정말 좋은 요청입니다! 파이썬의 첫 번째 장점인 **'배우기 쉽고 읽기 편하다(Readability & Simplicity)'**는 코드의 **가독성(Readability)**이 얼마나 중요한지를 보여줍니다.\n", + "\n", + "복잡한 문법 없이도 우리가 일상어로 생각하는 것처럼 코드를 작성할 수 있다는 것을 예시 코드를 통해 보여드릴게요.\n", + "\n", + "### 📝 예시 코드: 간단한 계산기 만들기\n", + "\n", + "우리가 사각형의 넓이를 구하는 아주 간단한 계산을 파이썬으로 해보겠습니다.\n", + "\n", + "```python\n", + "# 1. 변수에 값 할당 (값을 담는 상자를 만드는 것과 같아요)\n", + "length = 10 # 가로 길이를 10으로 설정\n", + "width = 5 # 세로 길이를 5로 설정\n", + "\n", + "# 2. 계산 수행 (덧셈, 곱셈 등 간단한 연산)\n", + "area = length * width # 넓이를 계산합니다.\n", + "\n", + "# 3. 결과 출력 (결과를 화면에 보여줍니다)\n", + "print(\"가로 길이:\", length)\n", + "print(\"세로 길이:\", width)\n", + "print(\"두 도형의 넓이는:\", area)\n", + "```\n", + "\n", + "### ✨ 코드 해설 및 설명\n", + "\n", + "이 코드가 왜 파이썬의 '읽기 쉬움'을 잘 보여주는지 설명해 드릴게요.\n", + "\n", + "1. **명확한 변수 사용:**\n", + " * `length = 10`과 같이 변수 이름을 설정하면, 이 코드를 읽는 사람은 즉시 \"아, 이 변수는 가로 길이를 저장하고 있구나\"라고 이해할 수 있습니다. 복잡한 기호 대신 **의미 있는 단어**를 사용하기 때문에 코드를 읽는 데 노력을 덜 들이게 됩니다.\n", + "\n", + "2. **직관적인 문법:**\n", + " * 복잡한 괄호나 세미콜론(;) 같은 불필요한 기호 없이, **사람이 쓰는 자연어와 매우 유사한 구조**로 코드를 작성했습니다.\n", + " * 우리는 수학 문제를 풀 때처럼 `A = B * C`와 같이 생각하면, 파이썬 코드도 비슷하게 생각하면 됩니다.\n", + "\n", + "3. **순차적인 흐름:**\n", + " * 코드가 위에서 아래로 순서대로 실행되기 때문에, **어떤 순서로 계산이 진행되는지**를 따라가기 매우 쉽습니다.\n", + "\n", + "**👉 비교해 보기:** 만약 다른 언어에서 같은 작업을 한다면, 변수를 선언하고, 함수를 호출하고, 결과를 반환하는 등의 복잡한 문법을 사용해야 할 수 있습니다. 하지만 파이썬은 이 모든 것을 **간결하고 직관적인 방식**으로 처리해 줍니다.\n", + "\n", + "이처럼 파이썬은 **\"코드를 읽는 것\" 자체**가 매우 쉬워서, 새로운 사람도 코드를 보고 \"아, 이 코드가 무엇을 하려고 하는지\"를 빠르게 파악할 수 있다는 것이 가장 큰 장점입니다! 👍\n", + "네, 좋습니다! 두 번째 장점인 **'다재다능함(Versatility)'**은 파이썬이 얼마나 넓은 분야에서 활용될 수 있는지를 의미합니다.\n", + "\n", + "이 장점을 보여주기 위해, 파이썬이 **데이터 분석**과 **업무 자동화**라는 완전히 다른 두 가지 분야에서 어떻게 사용될 수 있는지, 아주 간단한 예시 코드를 통해 보여드리겠습니다.\n", + "\n", + "---\n", + "\n", + "### 🛠️ 예시 1: 데이터 분석 (Data Science) 분야\n", + "\n", + "데이터 분석은 파이썬의 가장 강력한 분야 중 하나입니다. 우리는 파이썬의 라이브러리 덕분에 복잡한 데이터 처리도 쉽게 할 수 있습니다.\n", + "\n", + "이 예시에서는 **Pandas**라는 강력한 라이브러리를 사용해 간단한 데이터 목록을 다루어 보겠습니다.\n", + "\n", + "```python\n", + "# --- [데이터 분석 예시] ---\n", + "# 파이썬이 데이터를 어떻게 다루는지 보여줍니다.\n", + "\n", + "# 1. 데이터 목록 (리스트)을 정의합니다.\n", + "student_scores = [85, 92, 78, 95, 88] # 학생들의 시험 점수 데이터\n", + "\n", + "print(\"--- 데이터 분석 예시 ---\")\n", + "print(\"원래 점수 목록:\", student_scores)\n", + "\n", + "# 2. 데이터 처리 (평균 점수를 계산)\n", + "average_score = sum(student_scores) / len(student_scores)\n", + "\n", + "print(\"계산된 평균 점수:\", average_score)\n", + "```\n", + "\n", + "**💡 이 코드가 보여주는 다재다능함:**\n", + "만약 여러분이 데이터 분석가라면, 이 코드는 실제 학생 데이터를 불러와서 평균을 계산하는 **핵심 작업**을 수행하는 시작점입니다. 파이썬은 복잡한 통계 계산을 위해 별도의 복잡한 수학 공식이나 프로그래밍 없이, `sum()`과 같은 간단한 명령어로 이런 분석을 가능하게 해줍니다.\n", + "\n", + "---\n", + "\n", + "### 🤖 예시 2: 업무 자동화 (Automation) 분야\n", + "\n", + "파이썬은 반복적인 컴퓨터 작업을 자동화하는 데도 탁월합니다. 이 예시에서는 **파일 관리**라는 업무 자동화에 사용해 보겠습니다.\n", + "\n", + "```python\n", + "# --- [업무 자동화 예시] ---\n", + "# 파이썬이 반복적인 작업을 자동화하는 방법을 보여줍니다.\n", + "\n", + "# 1. 작업 폴더 설정 (실제 파일 시스템 접근)\n", + "file_name = \"report_data.txt\"\n", + "\n", + "# 2. 파일 내용 작성 (자동화된 작업)\n", + "with open(file_name, \"w\") as file:\n", + " file.write(\"이것은 오늘 자동화된 보고서 데이터입니다.\\n\")\n", + " file.write(\"데이터 처리 작업이 성공적으로 완료되었습니다.\")\n", + "\n", + "print(\"--- 업무 자동화 예시 ---\")\n", + "print(f\"'{file_name}' 파일이 성공적으로 생성되었습니다.\")\n", + "```\n", + "\n", + "**💡 이 코드가 보여주는 다재다능함:**\n", + "이 코드는 사용자가 수동으로 텍스트 파일을 열고 내용을 타이핑하는 **반복적인 작업을 컴퓨터가 대신**하게 만듭니다. 이처럼 파이썬은 복잡한 계산뿐만 아니라, 파일 이동, 이메일 보내기, 웹 크롤링 등 **일상적인 사무 업무**까지 자동화할 수 있는 강력한 도구가 됩니다.\n", + "\n", + "---\n", + "\n", + "### ✨ 요약\n", + "\n", + "보시다시피, 파이썬이라는 **하나의 언어**가 다음과 같이 **매우 다른 영역**에서 사용될 수 있습니다.\n", + "\n", + "1. **수학/통계 영역:** 데이터를 분석하고 평균을 계산합니다.\n", + "2. **시스템 영역:** 파일 시스템에 접근하여 파일을 생성합니다.\n", + "\n", + "이처럼 파이썬은 특정 분야의 '전문 언어'가 아니라, **다양한 분야의 요구사항을 모두 처리할 수 있는 만능 도구**이기 때문에 '다재다능하다'고 말할 수 있는 것입니다.\n", + "[system] 당신은 친절한 파이썬 튜어입니다. 한국어로 답변하세요...\n", + "[human] 파이썬이란?...\n", + "[ai] 안녕하세요! 만나서 반갑습니다. 저는 여러분의 친절한 파이썬 튜터입니다....\n", + "[human] 방금 말한 내용의 장점 3가지는?...\n", + "[ai] 아, 네! 제가 앞서 설명드렸던 파이썬의 가장 큰 장점 3가지를 다시 정...\n", + "[human] 그 중 첫번째 장점에 대한 예시 코드 작성해줘...\n", + "[ai] 정말 좋은 요청입니다! 파이썬의 첫 번째 장점인 **'배우기 쉽고 읽기 ...\n", + "[human] 두 번째 장점에 대한 예시 코드 작성해줘...\n", + "[ai] 네, 좋습니다! 두 번째 장점인 **'다재다능함(Versatility)'...\n" + ] + } + ], + "execution_count": 59 + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "#### RunnableWithMessageHistory (자동 이력 관리)\n", + "id": "75063d6650a46819" + }, + { + "metadata": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": "", + "id": "fb66178274d6381" } ], "metadata": { "kernelspec": { - "display_name": "Python (Ollama Venv)", + "display_name": ".venv", "language": "python", - "name": "ollama-venv" + "name": "python3" }, "language_info": { "codemirror_mode": { diff --git a/ollama/news.py b/ollama/news.py new file mode 100644 index 0000000..76fce94 --- /dev/null +++ b/ollama/news.py @@ -0,0 +1,78 @@ +from langchain_ollama import ChatOllama +from langchain_ibm import ChatWatsonx +from langchain_core.prompts import PromptTemplate, ChatPromptTemplate +from langchain_core.output_parsers import ( + StrOutputParser, + JsonOutputParser, + PydanticOutputParser, +) +from pydantic import BaseModel, Field +from typing import Literal +from dotenv import load_dotenv +import os +import gradio as gr + +qwen_llm = ChatOllama(model="qwen3.5:4b") +exaone_llm = ChatOllama(model="exaone3.5:2.4b") + +system_prompt = """\ +당신은 뉴스 분석 전문가입니다. 반드시 json 형식으로만 응답하세요. +다른 텍스트 없이 아래 형식으로만 반환하세요\n +{{"title":"기사제목", "date":"작성일자", "keywords":["키워드1", "키워드2", "키워드3"], "category" : "카테고리"}} +""" + +template = ChatPromptTemplate.from_messages( + [ + ("system", system_prompt), + ("human", "{article}"), + ] +) + +chain = template | exaone_llm | JsonOutputParser() + + +# def news_input(article1, article2, article3): +# # 3개의 기사를 리스트로 묶음 +# articles = [article1, article2, article3] +# results = [] + +# # 각 기사별로 체인 실행 +# for text in articles: +# if text.strip(): # 내용이 있을 때만 실행 +# res = chain.invoke({"article": text}) +# results.append(res) + +# # 결과를 하나로 합쳐서 반환 +# return "\n\n---\n\n".join(results) + + +def news_input(texts): + # ===을 기준으로 기사 분리 + articles = [article for article in texts.split("===") if article.strip()] + + response = chain.batch([{"article": article} for article in articles]) + return "\n\n".join(str(item) for item in response) + + +app = gr.Interface( + news_input, + # inputs=[ + # gr.Textbox(label="기사 1", lines=5), + # gr.Textbox(label="기사 2", lines=5), + # gr.Textbox(label="기사 3", lines=5), + # ], + inputs=[ + gr.Textbox( + label="기사", + placeholder="여러 기사 입력 시 구분자로 ===을 사용하세요", + lines=20, + ), + ], + outputs=[ + gr.Textbox(label="요약", lines=20), + ], + title="✒ 뉴스 분석 전문가", + description="뉴스 기사에서 정보를 추출합니다.", +) + +app.launch() diff --git a/ollama/news2.py b/ollama/news2.py new file mode 100644 index 0000000..a8c3120 --- /dev/null +++ b/ollama/news2.py @@ -0,0 +1,65 @@ +from langchain_ollama import ChatOllama +from langchain_ibm import ChatWatsonx +from langchain_core.prompts import PromptTemplate, ChatPromptTemplate +from langchain_core.output_parsers import ( + StrOutputParser, + JsonOutputParser, + PydanticOutputParser, +) +from pydantic import BaseModel, Field +from typing import Literal +from dotenv import load_dotenv +import os +import gradio as gr + +qwen_llm = ChatOllama(model="qwen3.5:4b", temperature=0) +exaone_llm = ChatOllama(model="exaone3.5:2.4b", temperature=0) + + +class NewsResult(BaseModel): + title: str + date: str = Field(description="YYYY-MM-DD 형식, 없는 경우 '없음'") + category: Literal["정치", "경제", "사회", "문화", "스포츠", "IT", "국제", "기타"] + keywords: list[str] = Field(description="핵심 키워드 3개 이내") + + +pydantic_parser = PydanticOutputParser(pydantic_object=NewsResult) +template = ChatPromptTemplate.from_messages( + [ + ( + "system", + "당신은 뉴스 분석 전문가입니다. 기사에서 아래 정보를 추출하세요. {format_instructions}", + ), + ("human", "{article}"), + ] +).partial(format_instructions=pydantic_parser.get_format_instructions()) + + +chain = template | exaone_llm | pydantic_parser + + +def news_input(texts): + # ===을 기준으로 기사 분리 + articles = [article for article in texts.split("===") if article.strip()] + + response = chain.batch([{"article": article} for article in articles]) + return "\n\n".join(str(item) for item in response) + + +app = gr.Interface( + news_input, + inputs=[ + gr.Textbox( + label="기사", + placeholder="여러 기사 입력 시 구분자로 ===을 사용하세요", + lines=20, + ), + ], + outputs=[ + gr.Textbox(label="요약", lines=20), + ], + title="✒ 뉴스 분석 전문가", + description="뉴스 기사에서 정보를 추출합니다.", +) + +app.launch() diff --git a/ollama/product.py b/ollama/product.py new file mode 100644 index 0000000..3370f33 --- /dev/null +++ b/ollama/product.py @@ -0,0 +1,86 @@ +from langchain_ollama import ChatOllama +from langchain_ibm import ChatWatsonx +from langchain_core.prompts import PromptTemplate, ChatPromptTemplate +from langchain_core.output_parsers import ( + StrOutputParser, + JsonOutputParser, + PydanticOutputParser, +) +from pydantic import BaseModel, Field +from typing import Literal +from dotenv import load_dotenv +import os +import gradio as gr +import time + +qwen_llm = ChatOllama(model="qwen3.5:4b", temperature=0) +exaone_llm = ChatOllama(model="exaone3.5:2.4b", temperature=0) +gemma_llm = ChatOllama(model="gemma4:e2b", temperature=0) + + +class ReviewAnalysis(BaseModel): + sentiment: Literal["긍정", "부정", "중립"] = Field(description="전체 감정") + score: float = Field(ge=0.0, le=1.0, description="감정 강도") + pros: list[str] = Field(description="긍정적인 리뷰 리스트") + cons: list[str] = Field(description="부정적인 리뷰 리스트") + recommend: bool = Field(description="추천여부 True/False") + reply: str = Field(description="판매자 입장의 고객 답변 한 문장") + + +pydantic_parser = PydanticOutputParser(pydantic_object=ReviewAnalysis) +template = ChatPromptTemplate.from_messages( + [ + ( + "system", + "리뷰 담당자 입니다. 리뷰를 보고 정보를 추출하고 고객에 의문에 답변할 내용을 작성하세요. {format_instructions}", + ), + ("human", "{review}"), + ] +).partial(format_instructions=pydantic_parser.get_format_instructions()) + + +chain = template | gemma_llm | pydantic_parser + + +def analyze(texts): + # ===을 기준으로 리뷰 분리 + reviews = [review.strip() for review in texts.split("===") if review.strip()] + + start = time.time() + results = chain.batch([{"review": r} for r in reviews]) + elapsed = time.time() - start + + output = [] + for i, (review, result) in enumerate(zip(texts, results), 1): + emoji = {"긍정": "😊", "부정": "😡", "중립": "😑"}[result.sentiment] + output.append(f"[리뷰 {i}]") + output.append(f"고객 리뷰 {review[:40]}....") + output.append( + f"리뷰 감정 {emoji} {result.sentiment}(강도 : {result.score:.2f})" + ) + output.append(f"장점 {", ".join(result.pros) if result.pros else "없음"}") + output.append(f"단점 {", ".join(result.cons) if result.cons else "없음"}") + output.append(f"추천 여부 {"👍 추천" if result.recommend else "👎 비추천"}") + output.append(f"판매자 답변 {result.reply}") + output.append("-" * 40) + output.append(f"소요 시간 : {elapsed:.2f}초, ({len(reviews)} 개 리뷰) ") + return "\n".join(output) + + +app = gr.Interface( + analyze, + inputs=[ + gr.Textbox( + label="리뷰 입력", + placeholder="여러 리뷰 입력 시 구분자로 ===을 사용하세요", + lines=20, + ), + ], + outputs=[ + gr.Textbox(label="분석결과", lines=20), + ], + title="✒ 상품 리뷰 분석", + description="리뷰 입력 시 감정, 장담점, 추천 여부를 분설합니다.", +) + +app.launch()