Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
# howeverpipecat - 实时语音智能体工程分发版 | Real-time Voice Agent Distribution

> **非官方声明(Non-Affiliation)**
> 本仓库为社区维护的衍生/二次开发版本,与上游项目及其权利主体不存在官方关联、授权背书或从属关系。
> **商标声明(Trademark Notice)**
> 相关项目名称、Logo 与商标归其各自权利人所有。本仓库仅用于说明兼容/来源,不主张任何商标权利。


<p align="center">
<img src="docs/assets/howeverpipecat-logo.svg" alt="howeverpipecat logo" width="760" />
</p>
Expand All @@ -19,6 +13,11 @@
[![License](https://img.shields.io/badge/License-BSD--2--Clause-16A34A)](./LICENSE)
[![Repository](https://img.shields.io/badge/Repo-however--yir%2Fhoweverpipecat-0EA5E9)](https://github.com/however-yir/howeverpipecat)

> **非官方声明(Non-Affiliation)**<br>
> `howeverpipecat` 是基于 `pipecat-ai/pipecat` 的社区维护衍生发行版,与上游项目及其权利主体不存在官方关联、授权背书或从属关系。<br>
> **商标声明(Trademark Notice)**<br>
> `Pipecat` 及相关项目名称、Logo 与商标归其各自权利人所有;本仓库仅用于说明上游来源与兼容关系。

---

## 目录
Expand Down Expand Up @@ -358,4 +357,4 @@ bash scripts/however_dependency_security_scan.sh
- Upstream 许可证:`LICENSE`(BSD-2-Clause)
- Fork 补充说明:`LICENSE.HOWEVER`

本仓用于工程开发、测试和部署实践。生产使用前,请自行完成安全、合规与稳定性评估。
本仓用于工程开发、测试和部署实践。生产使用前,请自行完成安全、合规与稳定性评估。
3 changes: 1 addition & 2 deletions scripts/however_naming_lint.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@

from __future__ import annotations

from pathlib import Path
import re
import sys

from pathlib import Path

ROOT = Path(__file__).resolve().parents[1]

Expand Down
2 changes: 1 addition & 1 deletion scripts/however_service_health.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

import argparse
import json
from pathlib import Path
import sys
from pathlib import Path

try:
from pipecat.utils.however_health import build_however_health_result
Expand Down
6 changes: 3 additions & 3 deletions src/pipecat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
# SPDX-License-Identifier: BSD 2-Clause License
#

import asyncio
import sys
from importlib.metadata import PackageNotFoundError, version as lib_version
from importlib.metadata import PackageNotFoundError
from importlib.metadata import version as lib_version

from loguru import logger

Expand Down Expand Up @@ -38,8 +40,6 @@ def version() -> str:
#
# See https://github.com/python/cpython/pull/98518

import asyncio

if sys.version_info < (3, 12):
import wait_for2

Expand Down
9 changes: 4 additions & 5 deletions src/pipecat/services/ollama/llm.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@

"""Ollama LLM service implementation for the Pipecat framework."""

from dataclasses import dataclass
import os
from typing import Optional
import warnings
from dataclasses import dataclass
from typing import Optional

from loguru import logger

Expand Down Expand Up @@ -77,9 +77,7 @@ def __init__(
default_settings.apply_update(settings)

resolved_base_url = (
base_url
or os.getenv("PIPECAT_OLLAMA_BASE_URL")
or "http://127.0.0.1:11434/v1"
base_url or os.getenv("PIPECAT_OLLAMA_BASE_URL") or "http://127.0.0.1:11434/v1"
)
super().__init__(
base_url=resolved_base_url,
Expand All @@ -106,6 +104,7 @@ class OLLamaLLMService(OllamaLLMService):
"""Deprecated alias for :class:`OllamaLLMService`."""

def __init__(self, *args, **kwargs):
"""Initialize legacy alias and emit a deprecation warning."""
warnings.warn(
"OLLamaLLMService is deprecated; use OllamaLLMService instead.",
DeprecationWarning,
Expand Down
31 changes: 26 additions & 5 deletions src/pipecat/utils/however_health.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@

from __future__ import annotations

import socket
import time
from dataclasses import asdict, dataclass
from urllib.parse import urlparse
from urllib.request import Request, urlopen
import socket
import time

from pipecat.utils.however_runtime_config import HoweverRuntimeConfig, load_however_runtime_config


@dataclass(frozen=True)
class CheckResult:
"""Represents the outcome of an individual dependency health check."""

name: str
status: str
detail: str
Expand All @@ -27,6 +29,7 @@ class CheckResult:

@property
def ok(self) -> bool:
"""Return ``True`` when the check status is successful."""
return self.status == "ok"


Expand All @@ -39,7 +42,11 @@ def _fault_type_from_error(name: str, detail: str) -> str:
lowered = detail.lower()
if "401" in lowered or "403" in lowered or "unauthorized" in lowered or "forbidden" in lowered:
return "auth_error"
if "connection refused" in lowered or "timed out" in lowered or "name or service not known" in lowered:
if (
"connection refused" in lowered
or "timed out" in lowered
or "name or service not known" in lowered
):
return "network_error"
if "invalid" in lowered or "must use one of" in lowered:
return "config_error"
Expand All @@ -53,7 +60,13 @@ def _check_tcp(name: str, host: str, port: int, timeout_s: float) -> CheckResult
try:
with socket.create_connection((host, port), timeout=timeout_s):
latency = int((time.monotonic() - start) * 1000)
return CheckResult(name=name, status="ok", detail=f"connected {host}:{port}", latency_ms=latency, fault_type="none")
return CheckResult(
name=name,
status="ok",
detail=f"connected {host}:{port}",
latency_ms=latency,
fault_type="none",
)
except OSError as exc:
latency = int((time.monotonic() - start) * 1000)
detail = f"{host}:{port} - {exc}"
Expand All @@ -73,7 +86,13 @@ def _check_http(name: str, url: str, timeout_s: float) -> CheckResult:
with urlopen(req, timeout=timeout_s) as resp:
latency = int((time.monotonic() - start) * 1000)
if 200 <= resp.status < 400:
return CheckResult(name=name, status="ok", detail=f"http {resp.status} {url}", latency_ms=latency, fault_type="none")
return CheckResult(
name=name,
status="ok",
detail=f"http {resp.status} {url}",
latency_ms=latency,
fault_type="none",
)
detail = f"http {resp.status} {url}"
return CheckResult(
name=name,
Expand All @@ -99,6 +118,7 @@ def run_however_checks(
*,
skip_network: bool = False,
) -> tuple[dict[str, object], list[CheckResult]]:
"""Run service dependency checks and return metadata plus detailed check results."""
resolved_cfg = cfg or load_however_runtime_config()
if skip_network:
checks = [
Expand Down Expand Up @@ -132,6 +152,7 @@ def build_however_health_result(
*,
skip_network: bool = False,
) -> dict[str, object]:
"""Build a JSON-serializable health report for however runtime dependencies."""
meta, checks = run_however_checks(cfg, skip_network=skip_network)
all_ok = all(item.ok for item in checks)
result = {
Expand Down
5 changes: 3 additions & 2 deletions src/pipecat/utils/however_runtime_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@

from __future__ import annotations

import os
from dataclasses import dataclass
from pathlib import Path
from typing import Mapping
from urllib.parse import urlparse
import os


def _parse_env_file(path: Path) -> dict[str, str]:
Expand Down Expand Up @@ -59,6 +59,8 @@ def _pick(

@dataclass(frozen=True)
class HoweverRuntimeConfig:
"""Normalized runtime configuration for however Pipecat services."""

env: str
region: str
db_url: str
Expand All @@ -74,7 +76,6 @@ def load_however_runtime_config(
environ: Mapping[str, str] | None = None,
) -> HoweverRuntimeConfig:
"""Load local deployment config from env and optional env file."""

path_env = Path(env_path)
file_env = _parse_env_file(path_env)
env_vars = dict(os.environ if environ is None else environ)
Expand Down
Loading