1070 lines
36 KiB
Plaintext
1070 lines
36 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "787728aa",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Hello! 👋 It's great to meet you. How can I assist you today? Feel free to ask me anything or let me know if you need help with something specific!\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from ollama import chat\n",
|
|
"\n",
|
|
"response = chat(\n",
|
|
" model='qwen3.5:4b',\n",
|
|
" messages=[{'role': 'user', 'content': 'Hello!'}],\n",
|
|
")\n",
|
|
"print(response.message.content)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "851a76dc",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"현재 대한민국의 대통령은 윤석열입니다. 그는 2022년 3월 9일 실시된 제20대 대통령 선거에서 당선되어 2022년 5월 10일부터 임기를 시작했습니다. 윤석열 대통령의 임기는 2027년까지 예정되어 있습니다.\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from ollama import chat\n",
|
|
"\n",
|
|
"response = chat(\n",
|
|
" model='qwen2.5',\n",
|
|
" messages=[{'role': 'user', 'content': '대한민국 대통령은 누구야?'}],\n",
|
|
")\n",
|
|
"print(response.message.content)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "055cf9a8",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Hello! How can I assist you today? 😊\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from ollama import chat\n",
|
|
"\n",
|
|
"response = chat(\n",
|
|
" model='deepseek-r1:1.5b',\n",
|
|
" messages=[{'role': 'user', 'content': 'Hello!'}],\n",
|
|
")\n",
|
|
"print(response.message.content)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "accd1b97",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"To solve this problem, we need to generate the Fibonacci sequence up to the nth term efficiently. The Fibonacci sequence is defined such that each number is the sum of the two preceding ones, starting from 0 and 1. \n",
|
|
"\n",
|
|
"### Approach\n",
|
|
"The approach used here is an iterative method to compute the Fibonacci numbers. This method is chosen for its efficiency in terms of both time and space complexity compared to a recursive approach. Here are the key steps:\n",
|
|
"\n",
|
|
"1. **Initialization**: Start with the first two Fibonacci numbers, 0 and 1.\n",
|
|
"2. **Iteration**: For each subsequent term up to n (excluding the initial two), compute the next number as the sum of the previous two terms.\n",
|
|
"3. **Update**: After computing a new term, update the variables holding the last two terms for the next iteration.\n",
|
|
"\n",
|
|
"This approach ensures that we do not store all previously computed values in memory, which optimizes both time and space complexity.\n",
|
|
"\n",
|
|
"### Solution Code\n",
|
|
"```python\n",
|
|
"def fibonacci(n):\n",
|
|
" if n <= 0:\n",
|
|
" raise ValueError(\"n must be a positive integer\")\n",
|
|
" elif n == 1:\n",
|
|
" return 0\n",
|
|
" elif n == 2:\n",
|
|
" return 1\n",
|
|
" else:\n",
|
|
" a, b = 0, 1\n",
|
|
" for _ in range(3, n + 1):\n",
|
|
" c = a + b\n",
|
|
" a = b\n",
|
|
" b = c\n",
|
|
" return b\n",
|
|
"```\n",
|
|
"\n",
|
|
"### Explanation\n",
|
|
"- **Initialization**: We start with the first two Fibonacci numbers: `a = 0` and `b = 1`.\n",
|
|
"- **Iteration Loop**: For each term from 3 to n, we compute the next Fibonacci number as `c = a + b`. Then, update `a` to be the previous `b`, and `b` to be the newly computed `c`.\n",
|
|
"- **Return Result**: After completing the loop up to n terms, return `b` which is the nth Fibonacci number.\n",
|
|
"\n",
|
|
"This method efficiently computes each term in linear time and constant space, making it suitable for large values of n.\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from ollama import chat\n",
|
|
"\n",
|
|
"response = chat(\n",
|
|
" model='deepseek-r1:1.5b',\n",
|
|
" messages=[{'role': 'user', 'content': '파이썬으로 피보나치 수열 구현해줘!'}],\n",
|
|
")\n",
|
|
"print(response.message.content)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "e332d754",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"물론입니다! 파이썬으로 피보나치 수열을 구현하는 다양한 방법이 있습니다. 여기서는 몇 가지 예를 들어 보겠습니다.\n",
|
|
"\n",
|
|
"### 1. 재귀 함수 사용\n",
|
|
"\n",
|
|
"재귀 함수를 이용한 간단한 구현입니다:\n",
|
|
"\n",
|
|
"```python\n",
|
|
"def fibonacci_recursive(n):\n",
|
|
" if n <= 0:\n",
|
|
" return \"피보나치 수열의 인덱스는 0 이상이어야 합니다.\"\n",
|
|
" elif n == 1:\n",
|
|
" return 0\n",
|
|
" elif n == 2:\n",
|
|
" return 1\n",
|
|
" else:\n",
|
|
" return fibonacci_recursive(n-1) + fibonacci_recursive(n-2)\n",
|
|
"\n",
|
|
"# 예시 호출\n",
|
|
"for i in range(1, 11):\n",
|
|
" print(f\"fibonacci({i}) = {fibonacci_recursive(i)}\")\n",
|
|
"```\n",
|
|
"\n",
|
|
"### 2. 반복 구조 사용\n",
|
|
"\n",
|
|
"반복문을 이용한 효율적인 구현입니다:\n",
|
|
"\n",
|
|
"```python\n",
|
|
"def fibonacci_iterative(n):\n",
|
|
" if n <= 0:\n",
|
|
" return \"피보나치 수열의 인덱스는 0 이상이어야 합니다.\"\n",
|
|
" \n",
|
|
" a, b = 0, 1\n",
|
|
" for _ in range(2, n + 1):\n",
|
|
" a, b = b, a + b\n",
|
|
" \n",
|
|
" return b\n",
|
|
"\n",
|
|
"# 예시 호출\n",
|
|
"for i in range(1, 11):\n",
|
|
" print(f\"fibonacci({i}) = {fibonacci_iterative(i)}\")\n",
|
|
"```\n",
|
|
"\n",
|
|
"### 3. 메모이제이션 사용 (Top-Down 동적 프로그래밍)\n",
|
|
"\n",
|
|
"재귀 함수와 함께 메모이제이션을 사용하여 효율성을 향상시키는 방법입니다:\n",
|
|
"\n",
|
|
"```python\n",
|
|
"def fibonacci_memoization(n, memo={}):\n",
|
|
" if n <= 0:\n",
|
|
" return \"피보나치 수열의 인덱스는 0 이상이어야 합니다.\"\n",
|
|
" \n",
|
|
" if n in memo:\n",
|
|
" return memo[n]\n",
|
|
" \n",
|
|
" if n == 1:\n",
|
|
" result = 0\n",
|
|
" elif n == 2:\n",
|
|
" result = 1\n",
|
|
" else:\n",
|
|
" result = fibonacci_memoization(n-1, memo) + fibonacci_memoization(n-2, memo)\n",
|
|
" \n",
|
|
" memo[n] = result\n",
|
|
" return result\n",
|
|
"\n",
|
|
"# 예시 호출\n",
|
|
"for i in range(1, 11):\n",
|
|
" print(f\"fibonacci({i}) = {fibonacci_memoization(i)}\")\n",
|
|
"```\n",
|
|
"\n",
|
|
"### 4. 동적 프로그래밍 (Bottom-Up)\n",
|
|
"\n",
|
|
"다음과 같이 배열을 사용하여 계산을 하여 메모리를 최소화할 수 있습니다:\n",
|
|
"\n",
|
|
"```python\n",
|
|
"def fibonacci_dp(n):\n",
|
|
" if n <= 0:\n",
|
|
" return \"피보나치 수열의 인덱스는 0 이상이어야 합니다.\"\n",
|
|
" \n",
|
|
" fib = [0, 1] + [0] * (n - 1)\n",
|
|
" for i in range(2, n + 1):\n",
|
|
" fib[i] = fib[i-1] + fib[i-2]\n",
|
|
" \n",
|
|
" return fib[n]\n",
|
|
"\n",
|
|
"# 예시 호출\n",
|
|
"for i in range(1, 11):\n",
|
|
" print(f\"fibonacci({i}) = {fibonacci_dp(i)}\")\n",
|
|
"```\n",
|
|
"\n",
|
|
"위의 각 예제는 피보나치 수열을 구현하는 방법을 보여줍니다. `n` 번째 피보나치 수를 반환합니다. 원하는 방식을 선택하여 사용하시면 됩니다.\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from ollama import chat\n",
|
|
"\n",
|
|
"response = chat(\n",
|
|
" model='qwen2.5',\n",
|
|
" messages=[{'role': 'user', 'content': '파이썬으로 피보나치 수열 구현해줘!'}],\n",
|
|
")\n",
|
|
"print(response.message.content)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "e1790fc7",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"부정.\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"messages = [\n",
|
|
" # 시스템 프롬프트\n",
|
|
" {\"role\" : \"system\", \"content\" : \"너는 문장의 감성을 긍정, 부정, 중립 중 하나로 분류하는 ai 야\"},\n",
|
|
" # 퓨샷\n",
|
|
" {\"role\" : \"user\", \"content\" : \"정말 만족스러운 서비스였어요.\"}, \n",
|
|
" {\"role\" : \"assistant\", \"content\" : \"긍정\"}, \n",
|
|
" {\"role\" : \"user\", \"content\" : \"다시는 이용 안할 것 같아요.\"}, \n",
|
|
" {\"role\" : \"assistant\", \"content\" : \"부정.\"}, \n",
|
|
" # 사용자 프롬프트\n",
|
|
" {\"role\" : \"user\", \"content\" : \"배송이 너무 늦었어요.\"}, \n",
|
|
"]\n",
|
|
"\n",
|
|
"response = chat(model='qwen2.5', messages=messages)\n",
|
|
"print(response.message.content)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "837d9824",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"안녕하세요! 저는 Qwen이라 합니다. 중국어와 한국어를 포함한 여러 언어로 대화할 수 있는 AI 어시스턴트입니다. 다양한 정보 제공과 질문 답변을 통해 도움이 되는 역할을 하고 있습니다. 오늘 무엇을 도와드릴까요?"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"response = chat(\n",
|
|
" model='qwen2.5',\n",
|
|
" messages=[{'role': 'user', 'content': '안녕 간단히 자기소개 해봐!'}],\n",
|
|
" stream=True\n",
|
|
")\n",
|
|
"\n",
|
|
"for chunk in response:\n",
|
|
" content = chunk['message']['content']\n",
|
|
" print(content, end='', flush=True)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f89a855d",
|
|
"metadata": {},
|
|
"source": [
|
|
"### 구조화된 출력(Structured Output)\n",
|
|
"- json 형태\n",
|
|
" - 사용자 프롬프트에 지정\n",
|
|
" - json 형식\n",
|
|
" - pydantic"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "07c11d11",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{\n",
|
|
" \"sentiment\": \"positive\",\n",
|
|
" \"score\": 1\n",
|
|
"}\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"prompt = \"\"\"\\\n",
|
|
"다음 문장의 감정을 분석하라.\n",
|
|
"JSON 으로만 반환하시오.\n",
|
|
"\n",
|
|
"\n",
|
|
"{\n",
|
|
" \"sentiment\" :\"\",\n",
|
|
" \"score\":0\n",
|
|
"}\n",
|
|
"\n",
|
|
"문장:\n",
|
|
"오늘 정말 행복한 하루였다.\n",
|
|
"\"\"\"\n",
|
|
"\n",
|
|
"response = chat(\n",
|
|
" model='qwen2.5',\n",
|
|
" messages=[{'role':'user', 'content':prompt}]\n",
|
|
"\n",
|
|
")\n",
|
|
"\n",
|
|
"print(response.message.content)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "07c11d11",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{\n",
|
|
" \"summary\": \"경찰이 5·18 민주화운동을 폄훼한 내용을 포함한 합성물을 만든 50대 여성 A씨를 체포했습니다.\",\n",
|
|
" \"sentiment\": \"중립\",\n",
|
|
" \"keywords\": [\"5·18 민主化運動\", \"合成物\", \"捏造新闻\", \"拘留\", \"女性\"]\n",
|
|
"}\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"prompt = \"\"\"\\\n",
|
|
"다음 뉴스기사를 분석하라.\n",
|
|
"JSON 으로만 반환하시오.\n",
|
|
"\n",
|
|
"\n",
|
|
"{\n",
|
|
" \"summary\" : \"\",\n",
|
|
" \"sentiment\" :\"\",\n",
|
|
" \"keywords\":[]\n",
|
|
"}\n",
|
|
"\n",
|
|
"기사:\n",
|
|
"신문 기사를 모방한 합성물로 5·18 민주화운동을 폄훼한 누리꾼이 경찰에 붙잡혔다.\n",
|
|
"\n",
|
|
"광주경찰청 사이버범죄수사대는 24일 5·18민주화운동 등에 관한 특별법 위반, 명예훼손, 업무방해 등 혐의로 50대 여성 A씨를 입건했다.\n",
|
|
"\"\"\"\n",
|
|
"\n",
|
|
"response = chat(\n",
|
|
" model='qwen2.5',\n",
|
|
" messages=[{'role':'user', 'content':prompt}]\n",
|
|
"\n",
|
|
")\n",
|
|
"\n",
|
|
"print(response.message.content)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "0eb2c319",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{\n",
|
|
" \"sentiment\": \"양호\",\n",
|
|
" \"score\": 0\n",
|
|
"}\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"schema = {\n",
|
|
" \"type\":\"object\",\n",
|
|
" \"properties\":{\n",
|
|
" \"sentiment\":{\"type\":\"string\",\"description\":\"sentiment\"},\n",
|
|
" \"score\":{\"type\":\"integer\", \"description\":\"score\"},\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"prompt = \"\"\"\\\n",
|
|
"다음 문장의 감정을 분석하라.\n",
|
|
"단, format으로 주어진 구조를 출력해줘\n",
|
|
"\n",
|
|
"문장:\n",
|
|
"오늘 정말 행복한 하루였다.\n",
|
|
"\"\"\"\n",
|
|
"\n",
|
|
"response = chat(\n",
|
|
" model='qwen2.5',\n",
|
|
" messages=[{'role':'user', 'content':prompt}],\n",
|
|
" format=schema\n",
|
|
")\n",
|
|
"\n",
|
|
"print(response.message.content)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "4be52eed",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"{\n",
|
|
" \"summary\": \"경찰이 모방 신문 기사로 5·18 민주화운동을 폄훼한 50대 여성 A씨를 체포하였다는 소식입니다.\",\n",
|
|
" \"sentiment\": \"neutral\",\n",
|
|
" \"keywords\": [\"5·18민주화운동\", \"명예훼손\", \"사이버범죄수사대\", \"합성물\", \"경찰 체포\"]\n",
|
|
"}\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"schema = {\n",
|
|
" \"type\":\"object\",\n",
|
|
" \"properties\":{\n",
|
|
" \"summary\":{\"type\":\"string\"},\n",
|
|
" \"sentiment\":{\"type\":\"string\",\"enum\":[\"positive\", \"neutral\", \"negative\"]},\n",
|
|
" \"keywords\":{\"type\":\"array\"},\n",
|
|
" },\n",
|
|
" \"required\":[\n",
|
|
" \"summary\", \"sentiment\", \"keywords\"\n",
|
|
" ]\n",
|
|
"}\n",
|
|
"\n",
|
|
"prompt = \"\"\"\\\n",
|
|
"다음 뉴스기사를 분석하라.\n",
|
|
"단, format으로 주어진 구조로 출력해줘.\n",
|
|
"한글로!\n",
|
|
"\n",
|
|
"기사:\n",
|
|
"신문 기사를 모방한 합성물로 5·18 민주화운동을 폄훼한 누리꾼이 경찰에 붙잡혔다.\n",
|
|
"\n",
|
|
"광주경찰청 사이버범죄수사대는 24일 5·18민주화운동 등에 관한 특별법 위반, 명예훼손, 업무방해 등 혐의로 50대 여성 A씨를 입건했다.\n",
|
|
"\"\"\"\n",
|
|
"\n",
|
|
"response = chat(\n",
|
|
" model='qwen2.5',\n",
|
|
" messages=[{'role':'user', 'content':prompt}],\n",
|
|
" format=schema\n",
|
|
")\n",
|
|
"\n",
|
|
"print(response.message.content)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "3088b0d0",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"sentiment='긍정' score=0.95\n",
|
|
"긍정\n",
|
|
"0.95\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from pydantic import BaseModel, Field\n",
|
|
"\n",
|
|
"class SentimentResult(BaseModel):\n",
|
|
" sentiment : str\n",
|
|
" score : float = Field(ge=0.0, le=1.0)\n",
|
|
" # keywords : list[str]\n",
|
|
"\n",
|
|
"prompt = \"\"\"\\\n",
|
|
"다음 문장의 감정을 분석하라.\n",
|
|
"단, format으로 주어진 구조를 출력해줘\n",
|
|
"\n",
|
|
"문장:\n",
|
|
"오늘 정말 행복한 하루였다.\n",
|
|
"\"\"\"\n",
|
|
"\n",
|
|
"response = chat(\n",
|
|
" model='qwen2.5',\n",
|
|
" messages=[{'role':'user', 'content':prompt}],\n",
|
|
" format=SentimentResult.model_json_schema()\n",
|
|
")\n",
|
|
"\n",
|
|
"result = SentimentResult.model_validate_json(response.message.content)\n",
|
|
"print(result)\n",
|
|
"\n",
|
|
"print(result.sentiment)\n",
|
|
"print(result.score)\n",
|
|
"# print(result.keywords)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "935146a2",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"['5·18 민주화운동', '합성물', '명예훼손', '경찰 수사', '50대 여성 A씨', '사이버범죄수사대']\n",
|
|
"negative\n",
|
|
"경찰이 5·18 민주화운동을 폄훼한 뉴스 기사 모방 합성물을 작성한 50대 여성이 검거되었습니다.\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# \"sentiment\":{\"type\":\"string\",\"enum\":[\"positive\", \"neutral\", \"negative\"]},\n",
|
|
"\n",
|
|
"from pydantic import BaseModel, Field\n",
|
|
"from typing import Literal\n",
|
|
"\n",
|
|
"class NewsResult(BaseModel):\n",
|
|
" summary : str\n",
|
|
" sentiment : Literal[\"positive\", \"neutral\", \"negative\"]\n",
|
|
" keywords : list[str]\n",
|
|
"\n",
|
|
"prompt = \"\"\"\\\n",
|
|
"다음 뉴스기사를 분석하라.\n",
|
|
"단, format으로 주어진 구조로 출력해줘.\n",
|
|
"한글로!\n",
|
|
"\n",
|
|
"기사:\n",
|
|
"신문 기사를 모방한 합성물로 5·18 민주화운동을 폄훼한 누리꾼이 경찰에 붙잡혔다.\n",
|
|
"\n",
|
|
"광주경찰청 사이버범죄수사대는 24일 5·18민주화운동 등에 관한 특별법 위반, 명예훼손, 업무방해 등 혐의로 50대 여성 A씨를 입건했다.\n",
|
|
"\"\"\"\n",
|
|
"\n",
|
|
"response = chat(\n",
|
|
" model='qwen2.5',\n",
|
|
" messages=[{'role':'user', 'content':prompt}],\n",
|
|
" format=NewsResult.model_json_schema()\n",
|
|
")\n",
|
|
"\n",
|
|
"result = NewsResult.model_validate_json(response.message.content)\n",
|
|
"print(result.keywords)\n",
|
|
"print(result.sentiment)\n",
|
|
"print(result.summary)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "734f5312",
|
|
"metadata": {},
|
|
"source": [
|
|
"### tool calling\n",
|
|
"- 정의된 함수를 호출"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "258bb684",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def calculater(a, b):\n",
|
|
" return a + b"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "5a85a23d",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"tools = [\n",
|
|
" {\n",
|
|
" \"type\": \"function\",\n",
|
|
" \"function\": {\n",
|
|
" \"name\": \"calculator\",\n",
|
|
" \"description\": \"두 숫자를 더한다.\",\n",
|
|
" \"parameters\": {\n",
|
|
" \"type\": \"object\",\n",
|
|
" \"properties\": {\n",
|
|
" \"a\": {\n",
|
|
" \"type\": \"integer\",\n",
|
|
" \"description\": \"첫 번째 숫자\"\n",
|
|
" },\n",
|
|
" \"b\": {\n",
|
|
" \"type\": \"integer\",\n",
|
|
" \"description\": \"두 번째 숫자\"\n",
|
|
" }\n",
|
|
" },\n",
|
|
" \"required\": [\"a\",\"b\"]\n",
|
|
" }\n",
|
|
" }\n",
|
|
" }\n",
|
|
"]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "4060bab7",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"response = chat(\n",
|
|
" mode='qwen2.5',\n",
|
|
" messages=[{'role':'user', 'content':\"25와 36을 더해줘\"}],\n",
|
|
" tools=tools\n",
|
|
")\n",
|
|
"\n",
|
|
"print(respons.message) # \"25와 36을 더해줘\""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "0372e988",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# llm 이 필요하다면 tool 실행\n",
|
|
"tool_call = response.message.tool_call[0]\n",
|
|
"args = tool_call.funcation.arguments\n",
|
|
"\n",
|
|
"result = calculator(args['a'], args['b'])\n",
|
|
"\n",
|
|
"# tool 실행 결과를 llm 보내기\n",
|
|
"\n",
|
|
"messages = [\n",
|
|
" {'role': 'user', 'content':\"25와 36을 더해줘\"},\n",
|
|
" respons.message,\n",
|
|
" {'role': 'tool', 'content':str(result)},\n",
|
|
"\n",
|
|
"]\n",
|
|
"\n",
|
|
"final_response = chat(model='qwen2.5', messages=messages)\n",
|
|
"print(final_respons.message.content)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "47792959",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"role='assistant' content='' thinking=None images=None tool_name=None tool_calls=[ToolCall(function=Function(name='get_weather', arguments={'city': '서울'}))]\n",
|
|
"Tool 실행: get_weather({'city': '서울'}) → {'temp': 22, 'condition': '맑음'}\n",
|
|
"현재 서울의 기온은 22도 Celsius로, 날씨는 맑습니다.\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"import ollama\n",
|
|
"import json\n",
|
|
"\n",
|
|
"# ① 실제로 실행될 함수들\n",
|
|
"def get_weather(city: str) -> dict:\n",
|
|
" # 실제로는 날씨 API 호출 — 여기선 더미 데이터\n",
|
|
" data = {\n",
|
|
" \"서울\": {\"temp\": 22, \"condition\": \"맑음\"},\n",
|
|
" \"부산\": {\"temp\": 25, \"condition\": \"흐림\"},\n",
|
|
" }\n",
|
|
" return data.get(city, {\"temp\": 0, \"condition\": \"알 수 없음\"})\n",
|
|
"\n",
|
|
"# ② LLM에게 \"이런 Tool이 있다\"고 알려주는 스키마\n",
|
|
"tools = [\n",
|
|
" {\n",
|
|
" \"type\": \"function\",\n",
|
|
" \"function\": {\n",
|
|
" \"name\": \"get_weather\",\n",
|
|
" \"description\": \"특정 도시의 현재 날씨를 조회한다\",\n",
|
|
" \"parameters\": {\n",
|
|
" \"type\": \"object\",\n",
|
|
" \"properties\": {\n",
|
|
" \"city\": {\n",
|
|
" \"type\": \"string\",\n",
|
|
" \"description\": \"날씨를 조회할 도시 이름 (예: 서울, 부산)\"\n",
|
|
" }\n",
|
|
" },\n",
|
|
" \"required\": [\"city\"]\n",
|
|
" }\n",
|
|
" }\n",
|
|
" }\n",
|
|
"]\n",
|
|
"\n",
|
|
"messages = [{\"role\": \"user\", \"content\": \"서울 날씨 알려줘\"}]\n",
|
|
"\n",
|
|
"# ③ LLM 호출 — Tool 목록 전달\n",
|
|
"response = ollama.chat(\n",
|
|
" model=\"qwen2.5\",\n",
|
|
" messages=messages,\n",
|
|
" tools=tools,\n",
|
|
")\n",
|
|
"\n",
|
|
"print(response.message)\n",
|
|
"\n",
|
|
"# ④ LLM이 Tool 호출을 요청했으면 실제로 실행\n",
|
|
"if response.message.tool_calls:\n",
|
|
" for tool_call in response.message.tool_calls:\n",
|
|
" name = tool_call.function.name\n",
|
|
" args = tool_call.function.arguments\n",
|
|
"\n",
|
|
" # 함수 이름으로 실제 함수 매핑\n",
|
|
" tool_map = {\"get_weather\": get_weather}\n",
|
|
" result = tool_map[name](**args)\n",
|
|
" print(f\"Tool 실행: {name}({args}) → {result}\")\n",
|
|
"\n",
|
|
" # ⑤ Tool 결과를 대화 이력에 추가\n",
|
|
" messages.append(response.message) # LLM의 tool_calls 메시지\n",
|
|
" messages.append({\n",
|
|
" \"role\": \"tool\",\n",
|
|
" \"content\": json.dumps(result, ensure_ascii=False),\n",
|
|
" })\n",
|
|
"\n",
|
|
"# ⑥ 결과를 포함해서 LLM에 다시 전달 → 최종 자연어 응답\n",
|
|
"final = ollama.chat(model=\"qwen2.5\", messages=messages)\n",
|
|
"print(final.message.content)\n",
|
|
"# \"서울의 현재 날씨는 22°C이며 맑습니다.\""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "de085430",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"ename": "AttributeError",
|
|
"evalue": "module 'ollama' has no attribute 'chat'",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
|
|
"\u001b[31mAttributeError\u001b[39m Traceback (most recent call last)",
|
|
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[22]\u001b[39m\u001b[32m, line 38\u001b[39m\n\u001b[32m 34\u001b[39m messages = [{\u001b[33m\"role\"\u001b[39m: \u001b[33m\"user\"\u001b[39m, \u001b[33m\"content\"\u001b[39m: \u001b[33m\"서울 날씨 보고 우산이 필요한지 알려줘\"\u001b[39m}]\n\u001b[32m 35\u001b[39m \n\u001b[32m 36\u001b[39m \u001b[38;5;66;03m# ── 자동 루프: Tool 호출이 없을 때까지 반복 ──\u001b[39;00m\n\u001b[32m 37\u001b[39m \u001b[38;5;28;01mwhile\u001b[39;00m \u001b[38;5;28;01mTrue\u001b[39;00m:\n\u001b[32m---> \u001b[39m\u001b[32m38\u001b[39m response = ollama.chat(model=\u001b[33m\"qwen2.5\"\u001b[39m, messages=messages, tools=tools)\n\u001b[32m 39\u001b[39m \n\u001b[32m 40\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28;01mnot\u001b[39;00m response.message.tool_calls:\n\u001b[32m 41\u001b[39m \u001b[38;5;66;03m# Tool 호출 없음 = 최종 답변\u001b[39;00m\n",
|
|
"\u001b[31mAttributeError\u001b[39m: module 'ollama' has no attribute 'chat'"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"import ollama, json\n",
|
|
"\n",
|
|
"# Tool 함수들\n",
|
|
"def get_weather(city):\n",
|
|
" return {\"temp\": 12, \"condition\": \"비\"}\n",
|
|
"\n",
|
|
"def need_umbrella(condition):\n",
|
|
" return {\"result\": condition in [\"비\", \"눈\"]}\n",
|
|
"\n",
|
|
"def calculate(expression):\n",
|
|
" return {\"result\": eval(expression)} # 실제론 안전한 파서 사용\n",
|
|
"\n",
|
|
"# Tool 스키마 목록\n",
|
|
"tools = [\n",
|
|
" {\"type\": \"function\", \"function\": {\n",
|
|
" \"name\": \"get_weather\",\n",
|
|
" \"description\": \"도시 날씨 조회\",\n",
|
|
" \"parameters\": {\"type\": \"object\",\n",
|
|
" \"properties\": {\"city\": {\"type\": \"string\"}},\n",
|
|
" \"required\": [\"city\"]}}},\n",
|
|
" {\"type\": \"function\", \"function\": {\n",
|
|
" \"name\": \"need_umbrella\",\n",
|
|
" \"description\": \"날씨 상태로 우산 필요 여부 판단\",\n",
|
|
" \"parameters\": {\"type\": \"object\",\n",
|
|
" \"properties\": {\"condition\": {\"type\": \"string\"}},\n",
|
|
" \"required\": [\"condition\"]}}},\n",
|
|
"]\n",
|
|
"\n",
|
|
"tool_map = {\n",
|
|
" \"get_weather\": get_weather,\n",
|
|
" \"need_umbrella\": need_umbrella,\n",
|
|
"}\n",
|
|
"\n",
|
|
"messages = [{\"role\": \"user\", \"content\": \"서울 날씨 보고 우산이 필요한지 알려줘\"}]\n",
|
|
"\n",
|
|
"# ── 자동 루프: Tool 호출이 없을 때까지 반복 ──\n",
|
|
"while True:\n",
|
|
" response = ollama.chat(model=\"qwen2.5\", messages=messages, tools=tools)\n",
|
|
"\n",
|
|
" if not response.message.tool_calls:\n",
|
|
" # Tool 호출 없음 = 최종 답변\n",
|
|
" print(response.message.content)\n",
|
|
" break\n",
|
|
"\n",
|
|
" messages.append(response.message)\n",
|
|
"\n",
|
|
" for tc in response.message.tool_calls:\n",
|
|
" name = tc.function.name\n",
|
|
" args = tc.function.arguments\n",
|
|
" result = tool_map[name](**args)\n",
|
|
" print(f\"[Tool] {name}({args}) → {result}\")\n",
|
|
"\n",
|
|
" messages.append({\n",
|
|
" \"role\": \"tool\",\n",
|
|
" \"content\": json.dumps(result, ensure_ascii=False),\n",
|
|
" })"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "1b261a1d",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"응답: 파이썬의 주요 장점은 다음과 같습니다:\n",
|
|
"\n",
|
|
"1. **간결성**: 파이썬 코드는 매우 간결하고 가독성이 높습니다. 이를테면, 같은 기능을 수행하는 C++나 Java와 비교해보더라도 파이썬에서는 훨씬 짧고 직관적인 문법으로 작성할 수 있습니다.\n",
|
|
"\n",
|
|
"2. **커뮤니티와 지원**: 파이썬은 매우 큰 규모의 커뮤니티를 가지고 있으며, 이 커뮤니티는 많은 라이브러리와 도구를 개발하고 공유합니다. 이런 이유로 새로운 사용자가 시작하기 쉽고, 문제 해결이나 특정 기능에 대한 도움을 얻는데도 매우 유용합니다.\n",
|
|
"\n",
|
|
"3. **다목적성**: 파이썬은 다양한 분야에서 활용할 수 있는 강력한 언어입니다. 웹 개발, 데이터 과학, 머신 러닝, 그래픽 프로그래밍 등 다양한 분야에서 파이썬을 사용할 수 있습니다.\n",
|
|
"\n",
|
|
"이 외에도 호환성과 플랫폼 독립성, 그리고 배우기 쉽고 유지 관리하기 쉬운 특징들도 파이썬의 장점으로 꼽힙니다.\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"import requests\n",
|
|
"\n",
|
|
"# ① Chat Completion - 기본 호출\n",
|
|
"response = requests.post(\n",
|
|
" \"http://localhost:11434/api/chat\",\n",
|
|
" json={\n",
|
|
" \"model\": \"qwen2.5\",\n",
|
|
" \"messages\": [\n",
|
|
" {\"role\": \"system\", \"content\": \"당신은 친절한 AI 어시스턴트입니다.\"},\n",
|
|
" {\"role\": \"user\", \"content\": \"파이썬의 장점을 3가지 알려주세요.\"},\n",
|
|
" ],\n",
|
|
" \"stream\": False,\n",
|
|
" },\n",
|
|
")\n",
|
|
"\n",
|
|
"data = response.json()\n",
|
|
"print(\"응답:\", data[\"message\"][\"content\"])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "b2b03ad1",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"ename": "AttributeError",
|
|
"evalue": "module 'ollama' has no attribute 'embed'",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[31m---------------------------------------------------------------------------\u001b[39m",
|
|
"\u001b[31mAttributeError\u001b[39m Traceback (most recent call last)",
|
|
"\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[35]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m response = ollama.embed(\n\u001b[32m 2\u001b[39m model=\u001b[33m'qwen3-embedding:4b'\u001b[39m,\n\u001b[32m 3\u001b[39m input=\u001b[33m'The sky is blue because of Rayleigh scattering'\u001b[39m,\n\u001b[32m 4\u001b[39m )\n",
|
|
"\u001b[31mAttributeError\u001b[39m: module 'ollama' has no attribute 'embed'"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"\n",
|
|
"\n",
|
|
"response = ollama.embed(\n",
|
|
" model='qwen3-embedding:4b',\n",
|
|
" input='The sky is blue because of Rayleigh scattering',\n",
|
|
")\n",
|
|
"print(response.embeddings)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "f3b6034b",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"ename": "",
|
|
"evalue": "",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[1;31mRunning cells with 'Python 3.12.3' requires the ipykernel package.\n",
|
|
"\u001b[1;31mInstall 'ipykernel' into the Python environment. \n",
|
|
"\u001b[1;31mCommand: '/bin/python3 -m pip install ipykernel -U --user --force-reinstall'"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"!pip install numpy"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 38,
|
|
"id": "97c6625f",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# 코사인 유사도\n",
|
|
"from numpy import dot\n",
|
|
"from numpy.linalg import norm\n",
|
|
"\n",
|
|
"def cosine_similarity(a, b):\n",
|
|
" return dot(a, b) / (norm(a) * norm(b))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "e85ee4e5",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"ename": "NameError",
|
|
"evalue": "name 'ollama' 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[1]\u001b[39m\u001b[32m, line 5\u001b[39m\n\u001b[32m 1\u001b[39m \u001b[38;5;66;03m# 두 개의 문장이 유사한가?\u001b[39;00m\n\u001b[32m 2\u001b[39m s1 = \u001b[33m\"파이썬은 프로그래밍 언어이다\"\u001b[39m\n\u001b[32m 3\u001b[39m s2 = \u001b[33m\"Python은 개발에 사용되는 언어이다.\"\u001b[39m\n\u001b[32m 4\u001b[39m \n\u001b[32m----> \u001b[39m\u001b[32m5\u001b[39m e1 = ollama.embed(model=\u001b[33m'qwen3-embedding:4b'\u001b[39m, input=s1).embedding[\u001b[32m0\u001b[39m]\n\u001b[32m 6\u001b[39m e2 = ollama.embed(model=\u001b[33m'qwen3-embedding:4b'\u001b[39m, input=s2).embedding[\u001b[32m0\u001b[39m]\n\u001b[32m 7\u001b[39m \n\u001b[32m 8\u001b[39m print(cosine_similarity(e1,e2))\n",
|
|
"\u001b[31mNameError\u001b[39m: name 'ollama' is not defined"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# 두 개의 문장이 유사한가?\n",
|
|
"s1 = \"파이썬은 프로그래밍 언어이다\"\n",
|
|
"s2 = \"Python은 개발에 사용되는 언어이다.\"\n",
|
|
"\n",
|
|
"e1 = ollama.embed(model='qwen3-embedding:4b', input=s1).embedding[0]\n",
|
|
"e2 = ollama.embed(model='qwen3-embedding:4b', input=s2).embedding[0]\n",
|
|
"\n",
|
|
"print(cosine_similarity(e1,e2))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "487edd1a",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"ename": "",
|
|
"evalue": "",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[1;31mRunning cells with 'Python 3.12.3' requires the ipykernel package.\n",
|
|
"\u001b[1;31m<a href='command:jupyter.createPythonEnvAndSelectController'>Create a Python Environment</a> with the required packages."
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"documents = [\n",
|
|
" \"파이썬은 프로그래밍 언어이다\",\n",
|
|
" \"축구는 세계적으로 인기있는 스포츠이다.\",\n",
|
|
" \"인공지능은 머신러닝을 활용한다\",\n",
|
|
" \"서울은 대한민국의 수도이다\",\n",
|
|
"]\n",
|
|
"\n",
|
|
"doc_vectors =[]\n",
|
|
"\n",
|
|
"for doc in documnets:\n",
|
|
" vector = ollama.embed(model='qwem3-embedding:4b', input=doc).embedding[0]\n",
|
|
" doc_vectors.append(vector)\n",
|
|
"\n",
|
|
"query = \"AI 기술이란?\"\n",
|
|
"query_vector = ollama.embed(model='qwem3-embedding:4b', input=query).embedding[0]\n",
|
|
"\n",
|
|
"scores = []\n",
|
|
"for doc, vec in zip(documents, doc_vectors):\n",
|
|
" score = cosine_similarity(query_vector,vec)\n",
|
|
" scores.append((doc, score))\n",
|
|
"\n",
|
|
"scores.sort(key=lambda x:x[1], reversed=True)\n",
|
|
"\n",
|
|
"for doc, score in scores:\n",
|
|
" print(doc, score)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "892f1810",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"context = scores[0][0]\n",
|
|
"\n",
|
|
"prompt = f\"\"\"\n",
|
|
"문서 : \n",
|
|
"{context}\n",
|
|
"\n",
|
|
"질문 : \n",
|
|
"{query}\n",
|
|
"\"\"\"\n",
|
|
"\n",
|
|
"response = chat(model=\"qwen2.5:7b\", messages=[{\"role\":\"user\", \"content\":prompt}])\n",
|
|
"print(response.message.content)"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python (Ollama Venv)",
|
|
"language": "python",
|
|
"name": "ollama-venv"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.12.3"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|