Open WebUI 어드밴스드 백서: 파이프라인(Pipelines) 및 MCP 서버 연동

구분심화편 (Deep Dive)
버전Open WebUI v0.6.x (2026년 5월)
전제기초편(글 1~2) 완독 후 권장
난이도중급 ~ 전문가
Admin Panel 완전 정복 RAG 심화 Pipelines MCP 연동 Open Terminal 자동화·실전 레시피
기초편에서 Docker 설치와 기본 채팅을 익혔다면, 심화편에서는 Admin Panel 전체 메뉴 완전 정복, RAG 파이프라인 최적화, Pipelines·Functions·MCP 서버 연동, Open Terminal, 팀 운영을 위한 사용자 관리, 자동화·스케줄링, 실전 활용 레시피까지 다룹니다. Open WebUI를 단순 채팅 도구가 아닌 팀 AI 인프라로 완전히 활용합니다.
SECTIOND1

Admin Panel 완전 정복 — 모든 메뉴 설정 가이드

Admin Panel은 http://서버IP:3000/admin에서 접근합니다. 첫 번째 가입 계정이 자동으로 Admin 권한을 받습니다. 이후 가입자는 기본적으로 Pending 상태로 관리자 승인이 필요합니다.

👥 Users — 사용자 관리 완전 가이드

역할권한권장 대상설정 방법
Admin모든 설정·사용자 관리·모든 모델 접근시스템 관리자 1~2명Admin Panel → Users → 역할 변경
User채팅·Knowledge·개인 설정. Admin이 허용한 기능만일반 팀원승인 후 기본 역할
Pending로그인은 가능하지만 채팅 불가. 관리자 승인 대기신규 가입자DEFAULT_USER_ROLE=pending 설정
env — 사용자 가입·역할 관련 핵심 환경변수
# 신규 가입자 기본 역할 (pending 강력 권장 — 외부 공개 서버)
DEFAULT_USER_ROLE=pending

# 회원가입 허용/차단 (false: 관리자만 계정 생성 가능)
ENABLE_SIGNUP=true

# 이메일 도메인 화이트리스트 (회사 이메일만 허용)
# WEBUI_AUTH_TRUSTED_EMAIL_HEADER=

# 로그인 없이 사용 허용 (완전 공개 — 내부망 전용 시)
WEBUI_AUTH=true

# 관리자 이메일 (Docker 첫 실행 시 자동 Admin 계정 생성)
[email protected]

🔧 Settings → General — 기본 설정 완전 가이드

설정 항목설명권장값
Site Name브라우저 탭·로그인 화면에 표시되는 서비스 이름회사/팀명 + AI
Default Model신규 채팅 시 기본으로 선택되는 모델가장 많이 쓰는 모델
Default System Prompt모든 새 채팅에 자동으로 적용되는 시스템 프롬프트언어·톤·회사 규칙 포함
Enable Community Sharing사용자가 대화를 공개 공유할 수 있는지 여부기업 환경은 OFF
Enable Message Rating응답에 👍👎 평가 버튼 표시. Evaluation에 활용ON 권장
Enable User Locations지역 기반 컨텍스트 제공 여부필요 시 ON
JWT Expiration로그인 토큰 만료 시간 (초 단위)86400(1일) ~ 604800(7일)

🔌 Settings → Connections — 모델 연결 완전 설정

연결 유형URL 형식인증주요 사용처
Ollamahttp://ollama:11434없음(내부망)로컬 LLM 추론
OpenAI 호환https://api.openai.com/v1Bearer API KeyGPT-4o, Claude, Groq 등 모든 OpenAI 형식 API
Pipeline 서버http://pipelines:9099Pipeline API Key커스텀 파이프라인·필터·미들웨어
💡
OpenAI 호환 API로 Claude·Groq·DeepSeek 연결

Settings → Connections → Add OpenAI Connection
Anthropic Claude: URL = https://api.anthropic.com/v1 / Key = sk-ant-xxx
Groq: URL = https://api.groq.com/openai/v1 / Key = gsk_xxx
DeepSeek: URL = https://api.deepseek.com/v1 / Key = sk-xxx
OpenRouter: URL = https://openrouter.ai/api/v1 / Key = sk-or-xxx

📊 Analytics — 사용량 대시보드

Admin Panel → Analytics에서 인스턴스 전체 사용 현황을 확인합니다. 팀 AI 운영의 비용 관리와 모델 선택에 핵심적인 데이터를 제공합니다.

지표활용 방법
메시지 볼륨 (시간대별)피크 타임 파악 → 서버 스케일링 계획
토큰 소비량 (모델별)월간 API 비용 추정 → 예산 관리
모델 인기도 순위가장 많이 쓰이는 모델 파악 → 기본 모델 최적화
사용자별 활동과다 사용자 파악 → 사용량 제한 고려
Knowledge Base 조회자주 검색된 문서 파악 → RAG 품질 개선

🏆 Evaluation — 모델 성능 평가 시스템

사용자가 응답에 👍👎를 누를 때마다 ELO 점수가 업데이트됩니다. Arena 모드에서는 어떤 모델이 답했는지 모르는 상태에서 두 응답을 비교해 편향 없는 평가가 가능합니다.

평가 방식동작 방식활용
일반 대화 평가채팅 중 응답 아래 👍👎 클릭 → ELO 자동 갱신자연스러운 사용 중 평가
Arena 모드같은 질문에 2개 모델이 무작위 응답 → 블라인드 선택편향 없는 모델 비교
리더보드ELO 기반 모델 순위표팀에 맞는 최적 모델 선택
스냅샷 저장평가된 대화가 파인튜닝 데이터로 저장됨커스텀 파인튜닝 데이터셋 구축

📢 Banners — 시스템 공지 완전 설정

env — WEBUI_BANNERS 환경변수로 공지 설정
# 배너를 환경변수로 설정 (GitOps 방식)
# Admin Panel → Settings → Banners에서 GUI로도 설정 가능

WEBUI_BANNERS='[
  {
    "id": "maintenance-notice",
    "type": "warning",
    "title": "예정 점검 안내",
    "content": "2026년 6월 1일 오전 2~4시 서버 점검이 있습니다.",
    "dismissible": true,
    "timestamp": "2026-05-30"
  }
]'

# 배너 type 종류:
# "info"    → 파란색 (일반 공지)
# "success" → 초록색 (완료 알림)
# "warning" → 노란색 (주의 사항)
# "error"   → 빨간색 (긴급 공지)

🔔 Webhooks — 자동화 알림 설정

Webhook 유형트리거활용 예시
Admin Webhook신규 사용자 가입Slack으로 “새 사용자 홍길동이 가입했습니다” 알림
User Webhook장시간 요청 완료큰 문서 분석 완료 시 이메일/Slack 알림
Channel Webhook외부 서비스 → 채널 메시지CI/CD 빌드 완료 시 팀 채널에 자동 보고

🛡️ Settings → Security — 보안 설정 완전 가이드

보안 설정권장값설명
Enable API Key AuthON프로그래밍 방식 접근을 위한 API Key 발급 허용
Enable Password Reset이메일 설정 시 ON사용자 비밀번호 재설정 이메일 발송
Default User Rolepending외부 공개 서버는 반드시 pending
Enable New Sign Ups초기에만 ONAdmin 계정 생성 후 OFF 권장
Trusted Email HeaderNginx/CF 통해 전달SSO 구성 시 사용자 이메일 헤더 신뢰
SECTIOND2

Workspace 완전 가이드 — Models · Knowledge · Prompts · Tools

🤖 Models — 커스텀 AI 에이전트 만들기

Workspace → Models에서 기존 LLM을 기반으로 역할 특화 에이전트를 만들 수 있습니다. “Python 튜터”, “코드 리뷰어”, “법률 어시스턴트” 등 각 업무에 맞는 커스텀 에이전트를 팀이 공유합니다.

설정 항목설명활용 팁
Base Model에이전트의 기반이 되는 LLM 선택코딩은 Claude Sonnet, 빠른 답변은 Groq
System Prompt이 에이전트의 역할·규칙·제약 정의구체적일수록 좋음. 출력 형식 지정 포함
Knowledge이 에이전트가 참조할 Knowledge Base 연결사내 문서 연결 → 회사 전용 AI
Tools이 에이전트가 사용할 Tools 강제 바인딩웹 검색 에이전트: web_search Tool 바인딩
ParametersTemperature, Top-K, Max Tokens 등 파라미터창의적 작업: temp 0.8 / 정확한 분석: temp 0.1
Access Control특정 사용자·그룹만 이 에이전트 접근 가능법무팀 전용, 개발팀 전용 에이전트 분리
Dynamic Variables시스템 프롬프트에 {{USER_NAME}} {{CURRENT_DATE}} 삽입자동으로 현재 사용자·날짜 주입
text — 실전 커스텀 에이전트 시스템 프롬프트 예시
## 사내 법무 어시스턴트 "LexAI"

**역할**: 당신은 [회사명]의 전문 법무 AI 어시스턴트입니다.
**사용자**: {{USER_NAME}} ({{CURRENT_DATE}} 기준)

**핵심 지침**:
1. 첨부된 사내 법무 문서와 계약서 템플릿을 우선 참조하세요
2. 법적 조언은 반드시 "법무팀 검토를 거쳐야 합니다"라고 명시
3. 한국 법률 기준으로 답변 (해외 법률은 별도 명시)
4. 계약서 검토 시 리스크 항목을 ⚠️로 표시

**출력 형식**:
- 핵심 답변 → 상세 설명 → 주의사항 → 다음 단계 순서
- 계약 검토 시 수정 제안은 기존/수정 형식으로

**절대 금지**:
- 개인 법적 조언 (소송 관련 등)
- 계약서 임의 서명 권고
- 확인되지 않은 법률 인용

📚 Knowledge — Knowledge Base 완전 구성 가이드

1
Knowledge Base 생성 계획
하나의 대형 KB보다 주제별 소형 KB가 검색 정확도↑. 예: “기술 문서”, “HR 정책”, “제품 매뉴얼”로 분리. 각 에이전트에 관련 KB만 연결.
2
지원 파일 형식과 주의사항
PDF, DOCX, TXT, MD, PPTX, XLSX, CSV, HTML 지원. 스캔 PDF는 Tika·Docling·Mistral OCR 엔진 선택 필요. 비밀번호 보호 PDF는 처리 불가.
3
청킹(Chunking) 설정 최적화
짧은 기술 문서: Chunk 512 / Overlap 50. 긴 법률 문서: Chunk 1500 / Overlap 200. 청크가 너무 작으면 맥락 부족, 너무 크면 검색 정밀도 하락.
4
임베딩 모델 선택
한국어 포함: BAAI/bge-m3 (1024차원, 다국어 최강). 빠른 처리: nomic-embed-text (Ollama 내장). 고품질 영어: text-embedding-3-large.
5
RAG 검색 파라미터 튜닝
Top K: 3~7 (많을수록 맥락↑, 프롬프트↑). Relevance Threshold: 0.3~0.5 (낮을수록 넓게 검색). 하이브리드 검색 ON 권장.
6
Full Context Mode (전체 삽입)
청크 검색 대신 문서 전체를 컨텍스트에 주입. 작은 문서(1~5페이지)에 최적. 정확도 최고지만 토큰 사용량 증가.

⚡ Prompts — 프롬프트 라이브러리 구축

Workspace → Prompts에서 자주 쓰는 프롬프트를 슬래시 명령(/)으로 등록합니다. 팀 전체가 표준화된 프롬프트를 공유해 품질을 일관되게 유지합니다.

text — 슬래시 명령 프롬프트 예시 (채팅에서 /요약 입력)
# 프롬프트 이름: 요약
# 슬래시 명령: /요약
# 변수: {{text}} — 사용자가 입력할 텍스트

다음 내용을 요약해주세요:

**핵심 요약** (3문장 이내):
[핵심 내용]

**주요 포인트** (불릿 포인트):
• 포인트 1
• 포인트 2
• 포인트 3

**액션 아이템** (있는 경우):
• 해야 할 일 1

원문: {{text}}

---
# 프롬프트 이름: 코드 리뷰
# 슬래시 명령: /리뷰
# 변수: {{language}}, {{code}}

다음 {{language}} 코드를 리뷰해주세요:

**버그/오류** ❌: [발견된 문제]
**성능 개선** ⚡: [최적화 제안]
**보안 취약점** 🔒: [보안 이슈]
**코드 품질** 📝: [가독성·유지보수성]
**수정 제안** ✅: [개선된 코드]

```{{language}}
{{code}}
```

🔧 Tools — Python 도구 작성 가이드

Workspace → Tools에서 Python으로 AI가 호출할 수 있는 실제 도구를 작성합니다. AI가 대화 중 필요하다고 판단하면 자동으로 도구를 호출합니다.

python — Tool 작성 예시: 환율 조회 + 날씨 + 회사 DB 조회
"""
title: 환율 조회 도구
description: 실시간 환율을 조회합니다
author: your-name
version: 1.0.0
"""

import requests
from datetime import datetime


class Tools:

    def __init__(self):
        pass

    def get_exchange_rate(
        self,
        from_currency: str,
        to_currency: str,
        amount: float = 1.0
    ) -> str:
        """
        실시간 환율을 조회합니다.
        :param from_currency: 기준 통화 (예: USD, EUR, JPY)
        :param to_currency: 변환할 통화 (예: KRW)
        :param amount: 변환할 금액 (기본: 1.0)
        :return: 환율 정보 문자열
        """
        try:
            url = f"https://api.exchangerate-api.com/v4/latest/{from_currency}"
            response = requests.get(url, timeout=5)
            data = response.json()

            rate = data["rates"].get(to_currency)
            if not rate:
                return f"오류: {to_currency} 환율 정보를 찾을 수 없습니다."

            converted = amount * rate
            return (
                f"💱 **{from_currency} → {to_currency} 환율**\n"
                f"기준일: {data['date']}\n"
                f"1 {from_currency} = {rate:,.2f} {to_currency}\n"
                f"{amount:,.0f} {from_currency} = **{converted:,.0f} {to_currency}**"
            )
        except Exception as e:
            return f"환율 조회 실패: {str(e)}"

    def get_current_weather(
        self,
        city: str,
        country_code: str = "KR"
    ) -> str:
        """
        현재 날씨를 조회합니다.
        :param city: 도시명 (영어 또는 한국어)
        :param country_code: 국가 코드 (기본: KR)
        :return: 날씨 정보 문자열
        """
        try:
            # OpenWeatherMap API (무료 키 필요)
            api_key = "YOUR_OPENWEATHERMAP_API_KEY"
            url = f"https://api.openweathermap.org/data/2.5/weather"
            params = {"q": f"{city},{country_code}", "appid": api_key,
                      "units": "metric", "lang": "kr"}
            response = requests.get(url, params=params, timeout=5)
            data = response.json()

            if data.get("cod") != 200:
                return f"날씨 정보를 찾을 수 없습니다: {city}"

            weather = data["weather"][0]["description"]
            temp = data["main"]["temp"]
            feels = data["main"]["feels_like"]
            humidity = data["main"]["humidity"]
            wind = data["wind"]["speed"]

            return (
                f"🌤️ **{city} 현재 날씨**\n"
                f"날씨: {weather}\n"
                f"기온: {temp:.1f}°C (체감 {feels:.1f}°C)\n"
                f"습도: {humidity}% | 바람: {wind}m/s"
            )
        except Exception as e:
            return f"날씨 조회 실패: {str(e)}"
SECTIOND3

RAG 심화 완전 가이드 — 벡터DB·청킹·임베딩·하이브리드 검색

🗄️ 지원 벡터 데이터베이스 완전 비교

벡터DB공식 지원특징권장 환경
ChromaDB✓ 공식기본값. 설치 없이 바로 사용. SQLite 기반소규모·개인·테스트
PGVector✓ 공식PostgreSQL 확장. 기존 PG 인프라 활용. SQL로 벡터 쿼리기업·기존 PostgreSQL 보유
Qdrant커뮤니티고성능 Rust 기반. 필터링 강력. 수백만 벡터에도 빠름대규모 KB·고성능 필요 시
Milvus커뮤니티엔터프라이즈급. 클러스터 지원. 수십억 벡터대기업·초대규모
Elasticsearch커뮤니티기존 ES 인프라 활용. 풀텍스트+벡터 통합이미 ES 사용 중인 팀
OpenSearch커뮤니티AWS 관리형. ES 호환. 클라우드 환경AWS 기반 팀
env — 벡터 DB 전환 환경변수 설정
# ── ChromaDB (기본값) ─────────────────────────────────
VECTOR_DB=chroma
# CHROMA_DATA_PATH=/app/backend/data/vector_db  # 기본 경로

# ── Qdrant (고성능 권장) ──────────────────────────────
VECTOR_DB=qdrant
QDRANT_URI=http://qdrant:6333
QDRANT_API_KEY=your_qdrant_api_key      # API Key 설정 시

# ── PGVector (PostgreSQL 기반) ───────────────────────
VECTOR_DB=pgvector
PGVECTOR_DB_URL=postgresql://user:password@postgres:5432/openwebui

# ── Milvus (대규모) ───────────────────────────────────
VECTOR_DB=milvus
MILVUS_URI=http://milvus:19530

📄 문서 추출 엔진 5가지 비교

추출 엔진강점약점설정 방법
PDFMiner (기본)빠름, 설치 불필요스캔 PDF·복잡한 레이아웃 취약기본값
Tika100+ 형식 지원, 메타데이터 추출Java 필요, 느림CONTENT_EXTRACTION_ENGINE=tika
Docling표·차트 구조 보존, PDF 레이아웃 이해무거운 모델 필요CONTENT_EXTRACTION_ENGINE=docling
Azure Document Intelligence스캔 OCR 최고 품질, 다국어유료 Azure 서비스Azure API Key 필요
Mistral OCRMistral 모델 기반 OCR, 한국어 강점Mistral API Key 필요CONTENT_EXTRACTION_ENGINE=mistral_ocr

⚙️ RAG 파라미터 최적화 완전 가이드

env — RAG 성능 최적화 환경변수 완전판
# ── 임베딩 모델 설정 ──────────────────────────────────
# 한국어 포함 다국어: BAAI/bge-m3 (권장, ~1.3GB)
RAG_EMBEDDING_MODEL=BAAI/bge-m3
RAG_EMBEDDING_ENGINE=ollama             # ollama | openai | local
RAG_OLLAMA_BASE_URL=http://ollama:11434

# OpenAI 임베딩 (빠르고 품질 높음, 유료)
# RAG_EMBEDDING_ENGINE=openai
# RAG_EMBEDDING_MODEL=text-embedding-3-large

# ── 청킹 설정 ─────────────────────────────────────────
# 기술 문서 (짧고 정밀)
CHUNK_SIZE=512
CHUNK_OVERLAP=50

# 법률/계약 문서 (길고 맥락 중요)
# CHUNK_SIZE=1500
# CHUNK_OVERLAP=200

# ── 검색 파라미터 ─────────────────────────────────────
# 검색 결과 반환 수 (많을수록 맥락 풍부, 토큰 사용 증가)
RAG_TOP_K=5

# 유사도 임계값 (0~1, 낮을수록 넓게 검색)
# 0.3: 넓게 검색 (재현율↑) / 0.6: 좁게 검색 (정밀도↑)
RELEVANCE_THRESHOLD=0.35

# 하이브리드 검색 (BM25 키워드 + 벡터 의미 검색 결합)
ENABLE_RAG_HYBRID_SEARCH=true

# 리랭킹 모델 (하이브리드 검색 결과 재정렬)
RAG_RERANKING_MODEL=BAAI/bge-reranker-v2-m3

# ── 웹 검색 설정 ──────────────────────────────────────
ENABLE_RAG_WEB_SEARCH=true
RAG_WEB_SEARCH_ENGINE=searxng
# SEARXNG_QUERY_URL=http://searxng:8080/search?q=&format=json

# Brave 웹 검색 (API Key 필요)
# RAG_WEB_SEARCH_ENGINE=brave
# BRAVE_SEARCH_API_KEY=BSAxxx

# ── 문서 추출 ─────────────────────────────────────────
CONTENT_EXTRACTION_ENGINE=tika          # 다양한 형식 지원
# TIKA_SERVER_URL=http://tika:9998      # Tika 서버 주소

🔍 Agentic RAG — AI가 자율적으로 문서를 검색하는 방식

기본 RAG는 사용자 질문에서 자동으로 벡터 검색을 실행합니다. Agentic RAG는 한 단계 더 나아가 AI 모델이 언제, 무엇을 검색할지 스스로 결정합니다. 모델이 Tool로서 Knowledge 검색 함수를 직접 호출해 복잡한 다단계 추론이 가능합니다.

text — Agentic RAG 활성화 및 동작 방식
# 채팅에서 파일 업로드 후 "#" 버튼 클릭 → Knowledge 검색 활성화

# 사용자: "당사 2024년 연간 보고서에서 영업이익률을 찾아서
#          2023년과 비교해줘"
#
# Agentic RAG 동작:
# 1. AI가 "annual_report_2024.pdf" 검색 필요 인식
# 2. search_knowledge("2024년 영업이익률") 함수 호출
# 3. search_knowledge("2023년 영업이익률") 함수 호출
# 4. 두 결과를 종합해 비교 분석

# Full Context Mode (작은 문서 전체 삽입)
# 채팅창 파일 첨부 → 파일 클릭 → "Full Context Mode" 활성화
SECTIOND4

Pipelines · Functions · MCP — 확장 시스템 완전 구현

🏗️ 확장 아키텍처 선택 가이드

레이어실행 위치최적 용도추가 인프라
Tools (Python)Open WebUI 프로세스 내API 호출, 계산, 데이터 조회 → AI가 호출없음
Functions (Python)Open WebUI 프로세스 내메시지 필터링, 새 모델 공급자 추가, UI 액션없음
MCP 서버외부 HTTP 서버기존 서비스 연결, 타사 SaaS, 복잡한 로직외부 서버 필요
Pipelines별도 Docker 컨테이너GPU 필요, 무거운 의존성, 격리 실행Docker 컨테이너

⚙️ Functions — 3종류 완전 가이드

🔧 Filter Function
메시지를 LLM 전후에 가로채 변환합니다. Input Filter: 사용자 메시지 → LLM 전달 전 처리 (PII 제거, 언어 변환, 컨텍스트 주입). Output Filter: LLM 응답 → 사용자 전달 전 처리 (형식 변환, 추가 정보 삽입).
🚇 Pipe Function
완전히 새로운 모델 공급자를 추가합니다. Ollama·OpenAI 외에 자체 API, 사내 모델, 특수 서비스를 마치 기본 모델처럼 채팅 드롭다운에 추가할 수 있습니다.
python — Filter Function 예시: PII 자동 마스킹
"""
title: PII 자동 마스킹 필터
description: 개인정보(주민번호, 신용카드, 전화번호)를 자동 마스킹
author: your-name
version: 1.0.0
"""

import re
from pydantic import BaseModel


class Filter:

    class Valves(BaseModel):
        # 관리자가 Admin Panel에서 설정하는 값
        priority: int = 0
        mask_ssn: bool = True        # 주민번호 마스킹
        mask_credit_card: bool = True # 신용카드 마스킹
        mask_phone: bool = True       # 전화번호 마스킹
        log_detections: bool = False  # 감지 로그 기록

    def __init__(self):
        self.valves = self.Valves()

    def inlet(self, body: dict, user: dict) -> dict:
        """사용자 메시지 → LLM 전달 전 처리 (Input Filter)"""
        messages = body.get("messages", [])

        for message in messages:
            if message.get("role") == "user":
                content = message.get("content", "")
                original = content

                if self.valves.mask_ssn:
                    # 주민번호 패턴: 000000-0000000
                    content = re.sub(
                        r'\b\d{6}-?\d{7}\b',
                        '[주민번호-마스킹]',
                        content
                    )

                if self.valves.mask_credit_card:
                    # 신용카드 패턴: 0000-0000-0000-0000
                    content = re.sub(
                        r'\b\d{4}[-\s]?\d{4}[-\s]?\d{4}[-\s]?\d{4}\b',
                        '[카드번호-마스킹]',
                        content
                    )

                if self.valves.mask_phone:
                    # 한국 전화번호: 010-0000-0000
                    content = re.sub(
                        r'\b0\d{1,2}-?\d{3,4}-?\d{4}\b',
                        '[전화번호-마스킹]',
                        content
                    )

                message["content"] = content

        return body

    def outlet(self, body: dict, user: dict) -> dict:
        """LLM 응답 → 사용자 전달 전 처리 (Output Filter)"""
        # 응답에도 혹시 PII가 있으면 마스킹
        messages = body.get("messages", [])
        for message in messages:
            if message.get("role") == "assistant":
                pass  # 필요 시 응답도 필터링
        return body
python — Pipe Function 예시: 사내 LLM API를 모델로 추가
"""
title: 사내 AI API 연결
description: 사내 구축 LLM을 Open WebUI 모델로 등록
author: your-name
version: 1.0.0
"""

import requests
from typing import Iterator, Generator
from pydantic import BaseModel


class Pipe:

    class Valves(BaseModel):
        INTERNAL_API_URL: str = "http://internal-llm.company.com/v1"
        INTERNAL_API_KEY: str = ""
        MODEL_ID: str = "company-internal-llm"

    def __init__(self):
        self.valves = self.Valves()
        self.id = "internal-llm"
        self.name = "사내 AI"  # 모델 드롭다운에 표시될 이름

    def get_models(self) -> list:
        """사용 가능한 모델 목록 반환"""
        return [
            {"id": self.valves.MODEL_ID, "name": "🏢 사내 AI (보안)"}
        ]

    def pipe(self, body: dict) -> Generator:
        """실제 추론 실행"""
        headers = {
            "Authorization": f"Bearer {self.valves.INTERNAL_API_KEY}",
            "Content-Type": "application/json"
        }

        response = requests.post(
            f"{self.valves.INTERNAL_API_URL}/chat/completions",
            headers=headers,
            json=body,
            stream=True,
            timeout=120
        )

        for line in response.iter_lines():
            if line:
                yield line.decode("utf-8")

🔗 MCP 서버 연동 — Model Context Protocol

Open WebUI v0.6+는 MCP Streamable HTTP를 네이티브로 지원합니다. MCP 서버를 연결하면 그 서버가 제공하는 Tool들을 AI가 자동으로 사용할 수 있습니다.

bash — MCP 서버 연결 방법
# Admin Panel → Settings → Connections → MCP Servers → Add

# 예시: Filesystem MCP 서버 (파일 읽기/쓰기)
# URL: http://mcp-filesystem:3000/mcp
# Name: Filesystem

# 예시: GitHub MCP 서버
# URL: https://api.githubcopilot.com/mcp/
# Name: GitHub

# 예시: n8n MCP 서버 (n8n 워크플로우 실행)
# URL: http://n8n:5678/mcp
# Name: n8n Automation

# Docker Compose에서 MCP 서버 함께 실행
# services:
#   mcp-filesystem:
#     image: mcp-server/filesystem:latest
#     volumes:
#       - ./data:/data:rw
#     ports:
#       - "3000:3000"

🔧 Pipelines — 별도 컨테이너 파이프라인 완전 가이드

yaml — Docker Compose에 Pipelines 서버 추가
services:
  open-webui:
    # ... 기존 설정 ...
    environment:
      # Pipelines 서버를 OpenAI 호환 API로 등록
      - OPENAI_API_BASE_URL=http://pipelines:9099
      - OPENAI_API_KEY=${PIPELINE_API_KEY}

  pipelines:
    image: ghcr.io/open-webui/pipelines:main
    container_name: pipelines
    restart: unless-stopped
    ports:
      - "9099:9099"
    volumes:
      # 파이프라인 Python 파일 저장 위치
      - pipelines_data:/app/pipelines
      # GPU 필요 시 NVIDIA 런타임 추가
    environment:
      - PIPELINES_API_KEY=${PIPELINE_API_KEY}

volumes:
  pipelines_data:
python — Pipeline 예시: 언어 자동 감지 + 번역 필터
"""
title: 자동 번역 파이프라인
description: 한국어 아닌 입력을 자동 감지하여 한국어로 번역 후 LLM에 전달
author: your-name
version: 1.0.0
"""

from typing import Generator
import requests


class Pipeline:

    def __init__(self):
        self.name = "자동 번역 파이프라인"
        self.type = "filter"

    def inlet(self, body: dict, user: dict) -> dict:
        messages = body.get("messages", [])

        for msg in messages:
            if msg.get("role") == "user":
                text = msg.get("content", "")

                # 영어 감지 (간단한 휴리스틱)
                ascii_ratio = sum(1 for c in text if c.isascii()) / max(len(text), 1)
                if ascii_ratio > 0.7 and len(text) > 20:
                    # DeepL 또는 Google 번역 API 호출
                    translated = self.translate_to_korean(text)
                    msg["content"] = f"[자동 번역됨]\n{translated}"

        return body

    def translate_to_korean(self, text: str) -> str:
        """번역 API 호출 (예시 — 실제 API로 교체)"""
        try:
            # DeepL Free API 예시
            url = "https://api-free.deepl.com/v2/translate"
            data = {
                "auth_key": "YOUR_DEEPL_API_KEY",
                "text": text,
                "target_lang": "KO"
            }
            response = requests.post(url, data=data, timeout=10)
            result = response.json()
            return result["translations"][0]["text"]
        except Exception:
            return text  # 번역 실패 시 원문 반환
SECTIOND5

Open Terminal · Channels · Notes · Calendar — 신기능 완전 활용

💻 Open Terminal — AI에게 실제 컴퓨터를 제공

Open Terminal은 Open WebUI v0.6의 가장 강력한 신기능입니다. AI가 실제 코드를 실행하고 결과를 확인하며 스스로 오류를 수정하는 진정한 코딩 에이전트가 됩니다.

기능설명활용 예시
코드 실행AI가 작성한 Python, Shell 코드를 실제로 실행하고 결과를 채팅으로 반환“데이터 분석 스크립트 짜고 바로 실행해줘”
파일 브라우저사이드바에서 파일 탐색·업로드·다운로드·편집. AI도 파일에 직접 접근결과 파일 다운로드, 대용량 파일 편집
웹사이트 미리보기AI가 만든 HTML/React 앱을 Terminal 내 Live Preview로 즉시 확인AI가 대시보드 만들어 → 즉시 미리보기
패키지 설치pip install, npm install 등 패키지 설치 후 즉시 활용“pandas 설치하고 CSV 분석해줘”
Docker 격리보안을 위해 Docker 컨테이너 내에서 격리 실행 (선택)서버 환경에서는 Docker 격리 권장
env — Open Terminal 설정
# Open Terminal 활성화
ENABLE_OPEN_TERMINAL=true

# 격리 실행 (Docker 컨테이너 내 코드 실행)
# 보안상 서버 환경에서는 true 권장
TERMINAL_EXECUTION_SANDBOX=true

# 실행 타임아웃 (초)
TERMINAL_EXECUTION_TIMEOUT=120

# 허용 패키지 설치 여부
TERMINAL_ALLOW_PACKAGE_INSTALL=true

📢 Channels — 팀 AI 협업 공간

Channels는 팀원이 함께 AI와 대화하는 공유 채팅 공간입니다. Slack 채널처럼 여러 사람이 같은 타임라인에서 여러 AI 모델을 호출해 협업합니다.

기능설명
@모델 태그@gpt-4o 또는 @claude로 특정 AI를 대화에 소환. 두 모델 의견 비교 가능
스레드 & 리액션메시지에 답글 스레드, 이모지 리액션. Slack과 동일한 UX
접근 제어Public / Private / 그룹 기반 / DM 채널 분리. 팀별 전용 채널
AI 채널 인식AI가 채널 대화 기록을 검색하고 참조해 맥락 있는 응답
Channel WebhookCI/CD, GitHub, 모니터링 서비스가 채널에 자동 메시지 게시

📝 Notes — AI와 함께하는 문서 워크스페이스

기능설명
Rich 에디터마크다운 + 서식 있는 텍스트. 플로팅 서식 도구바
AI Enhance텍스트 선택 → AI로 다시 쓰기·개선·번역. 인라인으로 즉시 반영
채팅에 첨부작성 중인 노트를 채팅에 첨부 → 청킹 없이 전체 내용 주입
AI 자율 접근Agentic 모드: AI가 노트를 검색·읽기·수정 자율 수행

📅 Calendar — 일정 연동 AI 비서

text — Calendar 기능 활용 방법
# Calendar 기능 위치: 사이드바 → Calendar 아이콘

# 지원 기능:
# - AI 대화 중 자동화 작업을 캘린더에 스케줄 등록
# - "매주 월요일 9시에 팀 브리핑 실행해줘" → 자동 캘린더 등록
# - iCal (.ics) 형식 내보내기/가져오기
# - 일정 기반 AI 자동 실행 트리거

# 활용 예시 (채팅에서):
# "이 리포트를 매월 첫째 주 금요일 오전에 자동으로 생성해줘"
# → AI가 자동으로 스케줄 등록 + 캘린더에 표시
SECTIOND6

채팅 심화 기능 완전 가이드

🔀 멀티모델 채팅 & Arena 모드

text — 멀티모델 채팅 사용 방법
# 방법 1: 멀티모델 비교 (같은 질문에 2개 모델 동시 응답)
# 채팅창 → 모델 선택 드롭다운 → "+" 버튼으로 모델 추가
# 최대 여러 모델을 나란히 배치해 응답 비교

# 방법 2: Arena 모드 (블라인드 A/B 테스트)
# Admin Panel → Evaluation → Arena Mode 활성화
# 채팅 시 어떤 모델인지 모르는 상태에서 두 응답 비교
# 더 좋은 응답 선택 → ELO 점수 자동 업데이트

# 방법 3: 대화 중 모델 전환
# 채팅 도중 모델 드롭다운에서 다른 모델 선택
# 이전 대화 컨텍스트를 유지한 채 새 모델로 계속 대화

⏱️ Automations — 채팅 기반 스케줄 자동화

v0.6에서 추가된 Automations 기능으로 AI에게 반복 작업을 자연어로 예약합니다.

text — Automations 사용 예시
# 채팅에서 자연어로 자동화 예약

사용자: "매일 오전 9시에 이 프롬프트를 자동으로 실행해줘:
        '오늘 날씨와 주요 IT 뉴스 3건을 정리해줘'"

Open WebUI: 자동화가 등록됐습니다! 매일 오전 9:00에 실행됩니다.
            [자동화 목록 보기] [지금 실행] [삭제]

# 자동화 관리:
# Settings → Automations (또는 채팅 → ⏱️ 아이콘)
# 자동화 목록, 실행 기록, 활성화/비활성화 관리

🧠 Memory — 대화를 넘어서는 사용자 기억

Memory 기능설명활성화 방법
자동 메모리AI가 대화에서 중요 정보를 자동으로 기억. “김철수는 Python 개발자”Settings → Personalization → Memory ON
수동 메모리 추가사용자가 직접 기억할 내용 입력Settings → Personalization → Memory → Add
메모리 조회채팅에서 “내가 무슨 기술 스택 쓴다고 했어?”자동으로 메모리 검색 후 응답
메모리 삭제오래됐거나 부정확한 기억 제거Settings → Memory → 개별 삭제

🎤 음성 & 이미지 심화 설정

env — 음성·이미지 생성 완전 설정
# ── STT (음성 → 텍스트) ───────────────────────────────
# 방법 A: OpenAI Whisper API (유료)
AUDIO_STT_ENGINE=openai
AUDIO_STT_MODEL=whisper-1

# 방법 B: 로컬 Whisper 서버 (무료, 자체 구축)
AUDIO_STT_ENGINE=openai
AUDIO_STT_OPENAI_API_BASE_URL=http://whisper:8000/v1
AUDIO_STT_OPENAI_API_KEY=any

# ── TTS (텍스트 → 음성) ───────────────────────────────
# 방법 A: OpenAI TTS
AUDIO_TTS_ENGINE=openai
AUDIO_TTS_VOICE=nova           # alloy, echo, fable, onyx, nova, shimmer

# 방법 B: ElevenLabs (더 자연스러운 한국어)
AUDIO_TTS_ENGINE=elevenlabs
AUDIO_TTS_API_KEY=sk_xxxx
AUDIO_TTS_VOICE=your_voice_id

# 방법 C: 로컬 Kokoro TTS
AUDIO_TTS_ENGINE=openai
AUDIO_TTS_OPENAI_API_BASE_URL=http://kokoro:8880/v1
AUDIO_TTS_OPENAI_API_KEY=any

# ── 이미지 생성 ───────────────────────────────────────
# DALL-E (OpenAI)
IMAGE_GENERATION_ENGINE=openai
IMAGE_SIZE=1024x1024
IMAGE_STEPS=50

# ComfyUI (로컬 AI 서버)
IMAGE_GENERATION_ENGINE=comfyui
COMFYUI_BASE_URL=http://comfyui:8188

# Automatic1111
IMAGE_GENERATION_ENGINE=automatic1111
AUTOMATIC1111_BASE_URL=http://a1111:7860
SECTIOND7

환경변수 완전 레퍼런스 — 운영 환경 최적화

env — Open WebUI 환경변수 완전판 (docker-compose .env)
## ════════════════════════════════════════════════
##  보안 & 인증 핵심 설정
## ════════════════════════════════════════════════

# JWT 서명 비밀키 (32자 이상 랜덤, 절대 노출 금지)
WEBUI_SECRET_KEY=your_very_long_random_secret_key_here

# 서비스 이름 (브라우저 탭·로그인 화면)
WEBUI_NAME=My Team AI

# 외부 공개 URL (OAuth 콜백 등에 사용)
WEBUI_URL=https://ai.yourcompany.com

# 회원가입 허용 (관리자 계정 생성 후 false 권장)
ENABLE_SIGNUP=true

# 신규 가입자 기본 역할 (외부 공개는 pending 필수!)
DEFAULT_USER_ROLE=pending

# JWT 만료 시간 (초, 86400=1일, 604800=7일)
JWT_EXPIRY=86400

## ════════════════════════════════════════════════
##  Ollama 연결
## ════════════════════════════════════════════════
OLLAMA_BASE_URL=http://ollama:11434

# 멀티 Ollama 서버 (부하 분산)
# OLLAMA_BASE_URLS=http://ollama1:11434;http://ollama2:11434

## ════════════════════════════════════════════════
##  데이터베이스
## ════════════════════════════════════════════════
# PostgreSQL (다중 사용자 팀 운영 권장)
DATABASE_URL=postgresql://user:password@postgres:5432/openwebui

# SQLite (기본값, 소규모·개인)
# DATABASE_URL=sqlite:////app/backend/data/webui.db

## ════════════════════════════════════════════════
##  RAG / 벡터 DB
## ════════════════════════════════════════════════
VECTOR_DB=qdrant
QDRANT_URI=http://qdrant:6333
QDRANT_API_KEY=your_qdrant_api_key

RAG_EMBEDDING_ENGINE=ollama
RAG_EMBEDDING_MODEL=BAAI/bge-m3
RAG_OLLAMA_BASE_URL=http://ollama:11434

CHUNK_SIZE=1000
CHUNK_OVERLAP=100
RAG_TOP_K=5
RELEVANCE_THRESHOLD=0.35
ENABLE_RAG_HYBRID_SEARCH=true
RAG_RERANKING_MODEL=BAAI/bge-reranker-v2-m3

## ════════════════════════════════════════════════
##  웹 검색
## ════════════════════════════════════════════════
ENABLE_RAG_WEB_SEARCH=true
RAG_WEB_SEARCH_ENGINE=searxng
SEARXNG_QUERY_URL=http://searxng:8080/search?q=&format=json

# 또는 Brave
# RAG_WEB_SEARCH_ENGINE=brave
# BRAVE_SEARCH_API_KEY=BSAxxxxxxxxx

## ════════════════════════════════════════════════
##  OAuth / SSO (선택)
## ════════════════════════════════════════════════
# Google OAuth
ENABLE_OAUTH_SIGNUP=true
OAUTH_PROVIDER_NAME=Google
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret

# Microsoft/Azure AD
# MICROSOFT_CLIENT_ID=your_client_id
# MICROSOFT_CLIENT_SECRET=your_client_secret
# MICROSOFT_TENANT_ID=your_tenant_id

## ════════════════════════════════════════════════
##  성능 & 고급
## ════════════════════════════════════════════════
# 워커 프로세스 수 (CPU 코어 수 - 1 권장)
WEBUI_WORKERS=4

# 파이프라인 서버
OPENAI_API_BASE_URL=http://pipelines:9099
OPENAI_API_KEY=your_pipeline_api_key

# Redis 세션 캐시 (멀티 워커 시 필수)
REDIS_URL=redis://:password@redis:6379/0

# 파일 업로드 최대 크기 (MB)
FILE_SIZE_LIMIT=100

# 이미지 생성
IMAGE_GENERATION_ENGINE=comfyui
COMFYUI_BASE_URL=http://comfyui:8188
SECTIOND8

실전 운영 레시피 15선 — 팀·기업·개발자

🏢 레시피 1 — 사내 문서 기반 AI (사내 GPT)

1
Knowledge Base 구성
Admin Panel → Knowledge → Create. 사내 문서(정책·제품 매뉴얼·회의록)를 PDF/DOCX로 업로드. 부서별 KB 분리: “HR 정책”, “기술 문서”, “영업 자료”
2
커스텀 에이전트 생성
Workspace → Models → New Model. KB 연결 + 시스템 프롬프트 작성. 예: “사내 HR AI는 회사 정책 문서를 기반으로 인사 규정 질문에 답합니다.”
3
접근 제어 설정
에이전트별로 특정 사용자 그룹만 접근 가능. HR 에이전트는 HR팀만, 법무 에이전트는 법무팀만.
4
팀원 초대 & 교육
Admin Panel → Users → Invite. DEFAULT_USER_ROLE=pending으로 승인제 운영. 사용법 안내 채널 생성.

🔍 레시피 2 — 코드 리뷰 봇 (GitHub Actions 연동)

python — Code Review Tool 작성
"""
title: GitHub PR 코드 리뷰
description: GitHub PR의 diff를 분석해 코드 리뷰 코멘트를 자동 게시
version: 1.0.0
"""

import requests


class Tools:

    def review_github_pr(
        self,
        repo: str,
        pr_number: int,
        github_token: str = ""
    ) -> str:
        """
        GitHub PR의 코드 변경사항을 가져옵니다.
        :param repo: 저장소명 (예: owner/repo)
        :param pr_number: PR 번호
        :return: diff 내용
        """
        headers = {
            "Authorization": f"Bearer {github_token}",
            "Accept": "application/vnd.github.v3.diff"
        }
        url = f"https://api.github.com/repos/{repo}/pulls/{pr_number}"
        response = requests.get(url, headers=headers)
        return response.text[:8000]  # 토큰 한도 고려

    def post_review_comment(
        self,
        repo: str,
        pr_number: int,
        body: str,
        github_token: str = ""
    ) -> str:
        """PR에 리뷰 코멘트를 게시합니다."""
        headers = {
            "Authorization": f"Bearer {github_token}",
            "Content-Type": "application/json"
        }
        url = f"https://api.github.com/repos/{repo}/issues/{pr_number}/comments"
        data = {"body": f"🤖 AI 코드 리뷰\n\n{body}"}
        response = requests.post(url, headers=headers, json=data)
        return "코멘트 게시 완료!" if response.ok else f"오류: {response.text}"

📊 레시피 3 — 데이터 분석 AI (Open Terminal 활용)

text — 데이터 분석 워크플로우
# 1. CSV 파일 업로드 (채팅창 첨부 또는 Open Terminal 파일 브라우저)

# 2. 채팅에서 요청:
"이 매출 데이터를 분석해줘:
- 월별 매출 추이 그래프
- 상위 5개 제품 파이차트
- 전년 대비 성장률 계산
- 이상치가 있으면 표시해줘
결과를 report.html로 저장해줘"

# 3. AI가 Open Terminal에서:
# pip install pandas matplotlib seaborn
# import pandas as pd, matplotlib.pyplot as plt
# df = pd.read_csv('data.csv')
# ... 분석 코드 자동 작성 및 실행 ...
# → 그래프 생성 → HTML 리포트 저장

# 4. 파일 브라우저에서 report.html 다운로드
# 또는 웹 미리보기로 즉시 확인

🌐 레시피 4 — Open WebUI를 API 서버로 활용

python — Open WebUI API를 외부 앱에서 호출
import requests # Admin Panel → Users → 사용자 클릭 → API Keys → Generate API Key OPENWEBUI_URL = “http://your-server:3000” API_KEY = “sk-your-openwebui-api-key” # OpenAI 호환 API 형식 response = requests.post( f”{OPENWEBUI_URL}/api/chat/completions”, headers={ “Authorization”: f”Bearer {API_KEY}”, “Content-Type”: “application/json” }, json={ “model”: “qwen2.5:14b”, # Ollama 모델명 “messages”: [ {“role”: “user”, “content”: “안녕하세요!”} ], “stream”: False } ) result = response.json() print(result[“choices”][0][“message”][“content”])

⚡ 레시피 5 — n8n + Open WebUI 완전 자동화 허브

text — n8n → Open WebUI API 연동 시나리오
# n8n 워크플로우: 이메일 수신 → AI 요약 → Slack 전송

# 1. n8n Gmail Trigger 노드: 새 이메일 수신 감지
# 2. HTTP Request 노드 (Open WebUI API 호출):
#    URL: http://open-webui:3000/api/chat/completions
#    Method: POST
#    Headers: Authorization: Bearer {API_KEY}
#    Body:
{
  "model": "claude-sonnet-4-5",
  "messages": [
    {
      "role": "system",
      "content": "이메일 내용을 3줄로 요약하고 중요도(높음/중간/낮음)를 판단해주세요."
    },
    {
      "role": "user",
      "content": "{{ $json.body }}"
    }
  ]
}

# 3. Slack 노드: AI 요약 결과를 #이메일-요약 채널에 전송
# 결과: 자동으로 이메일 요약 → Slack 알림

# Channel Webhook 활용:
# n8n에서 Open WebUI 채널 Webhook URL로 메시지 전송 가능
# URL: http://open-webui:3000/api/v1/channels/{channel_id}/messages/webhook

🔐 레시피 6 — Google OAuth SSO 설정 (기업 이메일 로그인)

env — Google OAuth 완전 설정
# 1. Google Cloud Console에서 OAuth 앱 생성:
#    API & Services → Credentials → OAuth 2.0 Client IDs
#    Redirect URI: https://ai.yourcompany.com/oauth/google/callback

# 2. 환경변수 설정
ENABLE_OAUTH_SIGNUP=true
OAUTH_MERGE_ACCOUNTS_BY_EMAIL=true    # 같은 이메일은 계정 통합

# Google OAuth
GOOGLE_CLIENT_ID=your_google_client_id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxx

# 특정 도메인만 허용 (회사 이메일)
OAUTH_ALLOWED_DOMAINS=yourcompany.com,subsidiary.com

# 신규 OAuth 가입자 자동 승인 (신뢰된 도메인이면 OK)
DEFAULT_USER_ROLE=user   # pending 대신 user로 자동 승인

🏭 레시피 7 — Filter Function으로 준법 감시 AI 구축

python — 준법 감시 Filter Function
“”” title: 준법 감시 필터 description: 금융·의료 규정 위반 키워드를 감지하고 AI 응답에 면책 문구 추가 version: 1.0.0 “”” from pydantic import BaseModel class Filter: class Valves(BaseModel): priority: int = 0 add_disclaimer: bool = True def __init__(self): self.valves = self.Valves() # 주의 키워드 self.sensitive_keywords = [ “투자 권고”, “매수 추천”, “확실히 오릅니다”, “의학적 진단”, “처방”, “치료법” ] def inlet(self, body: dict, user: dict) -> dict: “””입력 메시지에 민감 키워드 감지 시 시스템 지시 강화””” messages = body.get(“messages”, []) last_user_msg = “” for msg in messages: if msg.get(“role”) == “user”: last_user_msg = msg.get(“content”, “”) # 금융 관련 질문 감지 is_financial = any(kw in last_user_msg for kw in [“주식”, “투자”, “코인”, “암호화폐”]) if is_financial: # 시스템 프롬프트에 면책 지시 주입 body.setdefault(“messages”, []).insert(0, { “role”: “system”, “content”: “투자 조언 시 반드시 ‘이것은 투자 정보이며 투자 결정은 본인 판단하에 진행하세요’라는 문구를 마지막에 추가하세요.” }) return body def outlet(self, body: dict, user: dict) -> dict: “””응답에 자동 면책 문구 추가””” if not self.valves.add_disclaimer: return body messages = body.get(“messages”, []) for msg in messages: if msg.get(“role”) == “assistant”: content = msg.get(“content”, “”) if any(kw in content for kw in self.sensitive_keywords): msg[“content”] = content + “\n\n—\n⚠️ *이 내용은 참고용이며 전문가 상담을 권장합니다.*” return body
SECTIOND9

보안·성능 최적화·트러블슈팅 심화

🛡️ Nginx 리버스 프록시 완전 설정

nginx — open-webui.conf (WebSocket + SSL 완전판)
server { listen 80; server_name ai.yourcompany.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name ai.yourcompany.com; ssl_certificate /etc/letsencrypt/live/ai.yourcompany.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/ai.yourcompany.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; # 파일 업로드 크기 제한 client_max_body_size 100M; # WebSocket 지원 (스트리밍 응답 필수) location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection “upgrade”; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; # 긴 응답 타임아웃 (대형 모델 응답 시간 고려) proxy_read_timeout 600s; proxy_send_timeout 600s; proxy_connect_timeout 60s; # 버퍼링 비활성화 (스트리밍 응답) proxy_buffering off; proxy_cache off; } }

⚡ GPU & 성능 최적화

bash — Ollama GPU 성능 최적화 명령어
# GPU 메모리 사용 현황 확인
docker exec ai-ollama ollama ps

# Ollama 환경변수 성능 튜닝 (docker-compose.yml)
environment:
  - OLLAMA_NUM_PARALLEL=2        # 동시 요청 처리 수
  - OLLAMA_MAX_LOADED_MODELS=2   # VRAM 상주 모델 수
  - OLLAMA_FLASH_ATTENTION=1     # Ampere+ GPU: VRAM 절약
  - OLLAMA_KEEP_ALIVE=30m        # 모델 메모리 유지 시간
  - OLLAMA_MAX_QUEUE=512         # 대기열 최대 크기

# 모델 양자화 버전 사용 (VRAM 절약)
# Q4_K_M: 품질 대비 4배 압축
docker exec ai-ollama ollama pull qwen2.5:14b-instruct-q4_K_M

# Open WebUI 멀티 워커 (CPU 코어 활용)
WEBUI_WORKERS=4  # 환경변수로 설정

# Redis 캐시 (멀티 워커 세션 공유)
REDIS_URL=redis://:password@redis:6379/0

🔧 심화 트러블슈팅

증상원인해결 방법
RAG 검색 결과가 관련 없음청크 크기 또는 임베딩 모델 불일치Chunk Size 줄이기, bge-m3 한국어 모델로 변경, Threshold 낮추기
한국어 문서 RAG 품질 낮음영어 전용 임베딩 모델 사용RAG_EMBEDDING_MODEL=BAAI/bge-m3로 변경 후 문서 재인덱싱
스트리밍 응답 끊김Nginx proxy_read_timeout 너무 짧음nginx.conf에 proxy_read_timeout 600s 설정
WebSocket 연결 실패Nginx WebSocket 프록시 미설정Upgrade 헤더 설정 확인 (proxy_set_header Upgrade $http_upgrade)
Pipeline 연결 안 됨PIPELINE_API_KEY 불일치Open WebUI의 Connections API Key와 Pipeline env의 PIPELINES_API_KEY 일치 확인
파일 업로드 실패 (413)Nginx 업로드 크기 제한client_max_body_size 100M 추가
메모리 부족 (OOM)여러 모델 동시 VRAM 점유OLLAMA_MAX_LOADED_MODELS=1로 제한, KEEP_ALIVE 줄이기
OAuth 로그인 후 리다이렉트 실패WEBUI_URL 미설정 또는 오타WEBUI_URL을 정확한 공개 URL로 설정

📋 업데이트 & 백업 완전 가이드

bash — 안전한 업데이트 & 볼륨 백업
# ── 업데이트 (다운타임 최소화) ───────────────────────
# 1. 새 이미지 미리 다운로드
docker compose pull

# 2. 백업 먼저!
BACKUP_DIR=~/backups/openwebui-$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

# 3. 볼륨 백업 (서비스 중지 없이)
for vol in webui_data qdrant_data postgres_data; do
    echo "백업 중: $vol"
    docker run --rm \
        -v ${vol}:/data:ro \
        -v $BACKUP_DIR:/backup \
        alpine tar czf /backup/${vol}.tar.gz /data
done
echo "백업 완료: $BACKUP_DIR ($(du -sh $BACKUP_DIR | cut -f1))"

# 4. 업데이트 적용 (무중단 재시작)
docker compose up -d --no-deps open-webui
docker compose logs -f open-webui  # 정상 시작 확인

# ── 볼륨 복원 (재해 복구) ───────────────────────────
docker compose down
docker run --rm \
    -v webui_data:/data \
    -v $BACKUP_DIR:/backup \
    alpine tar xzf /backup/webui_data.tar.gz -C /
docker compose up -d
📋 Open WebUI 심화편 핵심 요약
  • Admin Panel: 사용자·모델·Analytics·Evaluation·Banners·Webhooks 완전 제어
  • Workspace: 역할 특화 에이전트·Knowledge Base·Prompt 라이브러리·Tool 바인딩
  • RAG 최적화: 9가지 벡터DB 선택·청킹 전략·bge-m3 한국어 임베딩·하이브리드 검색
  • 확장 시스템: Filter(PII 마스킹)·Pipe(새 모델 추가)·MCP 서버·Pipelines 컨테이너
  • 신기능: Open Terminal 코드 실행·팀 Channels·AI 협업 Notes·Calendar 스케줄
  • 운영: OAuth SSO·Nginx 설정·GPU 최적화·안전한 업데이트·볼륨 백업

🎉 Open WebUI 심화편 완독 완료! 이제 Open WebUI를 단순 채팅 도구가 아닌 팀 전체의 AI 인프라로 완전히 활용할 준비가 됐습니다. 사내 문서 AI, 자동화 파이프라인, 커스텀 에이전트까지 — 여러분만의 ChatGPT를 완성하세요.

Leave a reply

Please enter your comment!
Please enter your name here