1. 랭체인 이미지 인식 후 처리 마무리
2. fastAPI로 프로젝트 구조 실습 1. 랭체인 이미지 인식 후 처리 마무리 2. fastAPI로 프로젝트 구조 실습
This commit is contained in:
Generated
+10
@@ -0,0 +1,10 @@
|
||||
# 디폴트 무시된 파일
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 에디터 기반 HTTP 클라이언트 요청
|
||||
/httpRequests/
|
||||
# 쿼리 파일을 포함한 무시된 디폴트 폴더
|
||||
/queries/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
@@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
Generated
+4
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="~/Source/project/.venv" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/project.iml" filepath="$PROJECT_DIR$/.idea/project.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+11
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/rag_app/.venv" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="~/Source/project/.venv" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
Generated
+29
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PyToolsState">
|
||||
<option name="tools">
|
||||
<map>
|
||||
<entry key="pyrefly">
|
||||
<value>
|
||||
<ToolEntry />
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="pyright">
|
||||
<value>
|
||||
<ToolEntry />
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="ruff">
|
||||
<value>
|
||||
<ToolEntry />
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="ty">
|
||||
<value>
|
||||
<ToolEntry />
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,16 @@
|
||||
# 샘플 Python 스크립트입니다.
|
||||
|
||||
# Shift+F10을(를) 눌러 실행하거나 내 코드로 바꿉니다.
|
||||
# 클래스, 파일, 도구 창, 액션 및 설정을 어디서나 검색하려면 Shift 두 번을(를) 누릅니다.
|
||||
|
||||
|
||||
def print_hi(name):
|
||||
# 스크립트를 디버그하려면 하단 코드 줄의 중단점을 사용합니다.
|
||||
print(f'Hi, {name}') # 중단점을 전환하려면 Ctrl+F8을(를) 누릅니다.
|
||||
|
||||
|
||||
# 스크립트를 실행하려면 여백의 녹색 버튼을 누릅니다.
|
||||
if __name__ == '__main__':
|
||||
print_hi('PyCharm')
|
||||
|
||||
# https://www.jetbrains.com/help/pycharm/에서 PyCharm 도움말 참조
|
||||
@@ -0,0 +1,5 @@
|
||||
[project]
|
||||
name = "project"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = []
|
||||
Generated
+10
@@ -0,0 +1,10 @@
|
||||
# 디폴트 무시된 파일
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# 에디터 기반 HTTP 클라이언트 요청
|
||||
/httpRequests/
|
||||
# 쿼리 파일을 포함한 무시된 디폴트 폴더
|
||||
/queries/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
Generated
+13
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PortForwardingSettings">
|
||||
<ports>
|
||||
<entry key="8000">
|
||||
<ForwardedPortInfo>
|
||||
<option name="hostPort" value="8000" />
|
||||
<option name="readOnly" value="false" />
|
||||
</ForwardedPortInfo>
|
||||
</entry>
|
||||
</ports>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
Generated
+4
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="~/Source/project/rag_app/.venv" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/rag_app.iml" filepath="$PROJECT_DIR$/.idea/rag_app.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+34
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PyToolsState">
|
||||
<option name="tools">
|
||||
<map>
|
||||
<entry key="black">
|
||||
<value>
|
||||
<ToolEntry />
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="pyrefly">
|
||||
<value>
|
||||
<ToolEntry />
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="pyright">
|
||||
<value>
|
||||
<ToolEntry />
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="ruff">
|
||||
<value>
|
||||
<ToolEntry />
|
||||
</value>
|
||||
</entry>
|
||||
<entry key="ty">
|
||||
<value>
|
||||
<ToolEntry />
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+11
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="~/Source/project/rag_app/.venv" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,9 @@
|
||||
from langchain_ibm import WatsonxEmbeddings
|
||||
from backend.config.settings import settings
|
||||
|
||||
watson_embedding = WatsonxEmbeddings(
|
||||
model_id="ibm/granite-embedding-278m-multilingual",
|
||||
url=f"{settings.watsonx_url}",
|
||||
api_key=f"{settings.watsonx_api_key}",
|
||||
project_id=f"{settings.watsonx_project_id}",
|
||||
)
|
||||
@@ -0,0 +1,13 @@
|
||||
from langchain_ibm import ChatWatsonx
|
||||
from backend.config.settings import settings
|
||||
|
||||
watson_llm = ChatWatsonx(
|
||||
model_id="ibm/granite-4-h-small",
|
||||
url=f"{settings.watsonx_url}",
|
||||
api_key=f"{settings.watsonx_api_key}",
|
||||
project_id=f"{settings.watsonx_project_id}",
|
||||
max_tokens=2000,
|
||||
params={
|
||||
"temperature": 0
|
||||
}
|
||||
)
|
||||
@@ -0,0 +1,11 @@
|
||||
from pydantic import Field
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
class Settings(BaseSettings):
|
||||
model_config = SettingsConfigDict(env_file="backend/.env", extra="ignore")
|
||||
# 사용할 모델
|
||||
watsonx_api_key: str = Field(alias="WATSONX_API_KEY")
|
||||
watsonx_project_id: str = Field(alias="WATSONX_PROJECT_ID")
|
||||
watsonx_url: str = Field(alias="WATSONX_URL")
|
||||
|
||||
settings = Settings()
|
||||
@@ -0,0 +1,16 @@
|
||||
from fastapi import FastAPI
|
||||
from starlette.staticfiles import StaticFiles
|
||||
from backend.routers.page_router import router as page_router
|
||||
from backend.routers.api_router import router as api_router
|
||||
app = FastAPI()
|
||||
|
||||
app.include_router(page_router)
|
||||
app.include_router(api_router)
|
||||
|
||||
# static 폴더 지정
|
||||
app.mount("/static", StaticFiles(directory="backend/static"), name="static")
|
||||
|
||||
# http://127.0.0.1:8000/item/1 + GET
|
||||
# @app.get("/item/{item_id}")
|
||||
# async def read_item(item_id):
|
||||
# return {"item_id" : item_id}
|
||||
@@ -0,0 +1,25 @@
|
||||
from fastapi import APIRouter, Request, UploadFile
|
||||
from backend.services.llm_service import question_and_answer
|
||||
from backend.schemas.basic_schema import QuestionRequest
|
||||
from backend.services.rag_service import upload_document
|
||||
router = APIRouter(prefix="/api")
|
||||
|
||||
# http://127.0.0.1:8000/api/question
|
||||
@router.post("/question")
|
||||
async def question(req:QuestionRequest):
|
||||
answer = question_and_answer(req.question)
|
||||
|
||||
return {"message" : answer}
|
||||
|
||||
# http://127.0.0.1:8000/api/rag/upload
|
||||
@router.post("/rag/upload")
|
||||
async def fileUpload(file:UploadFile):
|
||||
# 서비스 호출
|
||||
return upload_document(file)
|
||||
|
||||
|
||||
# http://127.0.0.1:8000/api/rag/question
|
||||
|
||||
@router.post("/rag/question")
|
||||
async def question():
|
||||
pass
|
||||
@@ -0,0 +1,15 @@
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.templating import Jinja2Templates
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
templates = Jinja2Templates(directory="backend/templates")
|
||||
|
||||
# http://127.0.0.1:8000
|
||||
@router.get("/")
|
||||
async def home(request : Request):
|
||||
return templates.TemplateResponse(request = request, name="index.html")
|
||||
|
||||
@router.get("/rag")
|
||||
async def rag(request : Request):
|
||||
return templates.TemplateResponse(request = request, name="rag.html")
|
||||
@@ -0,0 +1,5 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
class QuestionRequest(BaseModel):
|
||||
question : str
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
from backend.ai.llm import watson_llm
|
||||
|
||||
# LLM 모델 통신
|
||||
# 데이터베이스 통신
|
||||
|
||||
def question_and_answer(question):
|
||||
response = watson_llm.invoke(question)
|
||||
return response.content
|
||||
@@ -0,0 +1,6 @@
|
||||
# pdf 업로드 => 분할 => 인덱스 생성
|
||||
def upload_document(file):
|
||||
pass
|
||||
|
||||
|
||||
# 질문 => 유사도 검색 => 문서 => llm 답변 생성
|
||||
@@ -0,0 +1,44 @@
|
||||
document.querySelector("button").addEventListener("click", ask)
|
||||
|
||||
async function ask() {
|
||||
// 사용자가 질문 입력 시 질문을 서버로 전송
|
||||
const question = document.querySelector('#question').value
|
||||
|
||||
const response = await fetch("/api/question", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
body: JSON.stringify({question : question})
|
||||
})
|
||||
// 전송 후 answer 도착 시 answer 화면에 보여주기
|
||||
const answer = await response.json()
|
||||
document.querySelector('#answer').textContent = answer.message
|
||||
}
|
||||
|
||||
// 파일 업로드
|
||||
document.querySelector("#uploadBtn").addEventListener("click", uploadFile)
|
||||
async function uploadFile()
|
||||
{
|
||||
const fileInput = document.querySelector("#file");
|
||||
// 첨부파일 정보 가져오기
|
||||
const file = fileInput.files[0];
|
||||
|
||||
if(!file)
|
||||
{
|
||||
alert("파일을 선택해주세요.");
|
||||
return;
|
||||
}
|
||||
|
||||
// form 만들어 전송
|
||||
const formData = new FormData()
|
||||
formData.append("file", file)
|
||||
|
||||
const response = await fetch("/api/reg/question", {
|
||||
method: "POST",
|
||||
body: formData
|
||||
})
|
||||
// 전송 후 answer 도착 시 answer 화면에 보여주기
|
||||
const answer = await response.json()
|
||||
document.querySelector('#answer').textContent = answer.message
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>HOME</h1>
|
||||
<ul>
|
||||
<a href="/rag">RAG</a>
|
||||
</ul>
|
||||
<div>
|
||||
<input type="text" name="question" id="question">
|
||||
<button type="submit">질문</button>
|
||||
</div>
|
||||
<div id="answer"></div>
|
||||
<script src="{{ url_for('static', path='js/index.js')}}"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>RAG</h2>
|
||||
<div>
|
||||
<input type="file" name="file" id="file">
|
||||
<button id="uploadBtn">업로드</button>
|
||||
</div>
|
||||
<hr>
|
||||
<div id="result"></div>
|
||||
<script src="{{ url_for('static', path='js/index.js')}}"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,5 @@
|
||||
[project]
|
||||
name = "rag-app"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = []
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "rag-app"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
Reference in New Issue
Block a user