-
Notifications
You must be signed in to change notification settings - Fork 8
Open
Description
- openwebui function code(pipeline) 을 dify와 연동
- openwebui에서 챗 시도
- 응답 내용 중 dify 인용부분 클릭
- 인용 팝업 화면에서 출처 URL link가 있습니다. -- 이걸 제거 하고 싶어요
** 인용 팝업 화면에서 URL 클릭 시 dify chunk 내용이 아니 자기 자신 페이지 링크로 업데이트 됩니다.
** dify에서 챗하면 응답 내용 중 인용클릭하면 팝업 후에 텍스트만 출력 됩니다.
** 이미지

** openwebui function code
"""
Title: Dify Simple Clean Version
Author: [email protected]
Version: 9.0.0 - 간단 명료 버전
Date: 2025.09.04
"""
import aiohttp
import json
from pydantic import BaseModel, Field
from typing import Optional, List, AsyncGenerator, Callable, Awaitable
class Pipe:
class Valves(BaseModel):
DIFY_BASE_URL: str = Field(default="http://localhost:8000")
DIFY_API_KEY: str = Field(default="app-xxxxxxxxxxxxxxxxx")
SHOW_CITATIONS: bool = Field(default=True)
CITATION_LENGTH: int = Field(default=500)
def __init__(self):
self.type = "manifold"
self.valves = self.Valves()
def pipelines(self) -> List[dict]:
return [{"id": "dify_format_final", "name": "Dify Format (Final)"}]
async def pipe(
self,
body: dict,
user: Optional[dict] = None,
__event_emitter__: Optional[Callable] = None,
) -> AsyncGenerator[str, None]:
try:
messages = body.get("messages", [])
user_message = messages[-1].get("content", "").strip() if messages else ""
if not user_message:
yield "메시지를 입력해주세요."
return
user_id = user.get("email", "user") if user else "anonymous"
url = f"{self.valves.DIFY_BASE_URL.rstrip('/')}/v1/chat-messages"
payload = {
"inputs": {},
"query": user_message,
"response_mode": "streaming",
"user": user_id,
}
headers = {
"Authorization": f"Bearer {self.valves.DIFY_API_KEY}",
"Content-Type": "application/json",
}
retriever_resources = []
in_citation_section = False
async with aiohttp.ClientSession() as session:
async with session.post(url, json=payload, headers=headers) as response:
if response.status != 200:
yield f"API 오류: {response.status}"
return
yield "\n"
async for line in response.content:
line_str = line.decode("utf-8", errors="replace").strip()
if not line_str.startswith("data: "):
continue
data_str = line_str[6:]
if data_str == "[DONE]":
break
try:
data = json.loads(data_str)
if data.get("event") == "message":
token = data.get("answer", "")
if token and token.strip() != "/":
# 스마트한 출처/참고 문서 차단
# 1. **로 시작하는 헤더 형태 차단
if token.strip().startswith("**") and any(
keyword in token.lower()
for keyword in [
"출처",
"참고",
"주의",
"추가",
"reference",
"citation",
]
):
in_citation_section = True
continue
# 2. 콜론으로 끝나는 라벨 형태 차단
if token.strip().endswith(":") and any(
keyword in token.lower()
for keyword in [
"출처",
"참고",
"주의사항",
"추가사항",
]
):
in_citation_section = True
continue
# 3. // 패턴 차단
if "//" in token:
in_citation_section = True
continue
# 4. 이미 citation 섹션에 들어간 경우 계속 차단
if in_citation_section:
continue
yield token
# 인용 정보 수집
if "metadata" in data:
metadata = data.get("metadata", {})
if (
"retriever_resources" in metadata
and not retriever_resources
):
retriever_resources = metadata[
"retriever_resources"
]
except json.JSONDecodeError:
continue
# 인용 처리 - 링크만 제거
if self.valves.SHOW_CITATIONS and __event_emitter__ and retriever_resources:
processed_docs = set()
citation_count = 0
for resource in retriever_resources:
document_name = resource.get("document_name", "Unknown Document")
if document_name in processed_docs:
continue
processed_docs.add(document_name)
content = resource.get("content", "")
if len(content) > self.valves.CITATION_LENGTH:
content = content[: self.valves.CITATION_LENGTH] + "..."
formatted_content = content.replace("\n\n", "\n\n• ")
if not formatted_content.startswith("• "):
formatted_content = "• " + formatted_content
# source 객체는 유지하되 링크 비활성화
citation_data = {
"document": [formatted_content],
"metadata": [
{"source": document_name, "type": "reference_only"}
],
"source": {
"name": document_name,
"type": "text", # type을 text로 설정해서 링크 비활성화 시도
},
}
await __event_emitter__({"type": "citation", "data": citation_data})
citation_count += 1
if citation_count > 0:
yield f"\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
yield f"\n\n**📚 {citation_count}개의 인용 및 참고 문서**\n"
except Exception as e:
yield f"오류: {str(e)}"
Metadata
Metadata
Assignees
Labels
No labels