Skip to content

Commit

Permalink
feat: 添加调用新入口qianfan.Qianfan (#761)
Browse files Browse the repository at this point in the history
* feat: add client for new entry

* feat: support chat.do call model as param

* feat: support chat.do call model as param

* fix: client

* fix: client

* fix: ut function

* feat: support console base url request custom

* debug try test

* fix: add thread debug info

* fix: conftest

* fix: rate limiter

* 设置限流器销毁时不等待线程退出

* 设置 poetry lock --no-update

* 删除 go_ci 中对 python 的路径判断

* 替换 golang rand.Seed

* fix: llm type for _local_models

---------

Co-authored-by: Dobiichi-Origami <[email protected]>
  • Loading branch information
danielhjz and Dobiichi-Origami authored Sep 3, 2024
1 parent 3a8d7e1 commit 2c90822
Show file tree
Hide file tree
Showing 52 changed files with 1,175 additions and 389 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/go_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ on:
branches: ['main']
paths:
- "go/**"
- "python/qianfan/tests/utils/mock_server.py"
- ".github/workflows/go_ci.yml"
pull_request:
paths:
- "go/**"
- "python/qianfan/tests/utils/mock_server.py"
- ".github/workflows/go_ci.yml"
workflow_dispatch:

Expand Down Expand Up @@ -41,7 +39,7 @@ jobs:
run: |
pip install poetry
echo "$HOME/.poetry/bin" >> $GITHUB_PATH
cd python && poetry lock
cd python && poetry lock --no-update
- name: Setup Python Cache
uses: actions/setup-python@v5
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/js_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
run: |
pip install poetry
echo "$HOME/.poetry/bin" >> $GITHUB_PATH
cd python && poetry lock
cd python && poetry lock --no-update
- name: Setup Python Cache
uses: actions/setup-python@v5
with:
Expand Down
12 changes: 7 additions & 5 deletions go/qianfan/chat_completion_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ var testEndpointList = []string{
"fjid_432",
}

var r = rand.New(rand.NewSource(time.Now().UnixNano()))

func TestChatCompletion(t *testing.T) {
for model, endpoint := range ChatModelEndpoint {
if model == "ERNIE-Function-8K" {
Expand Down Expand Up @@ -194,7 +196,7 @@ func TestChatCompletionModelList(t *testing.T) {
func TestChatCompletionRetry(t *testing.T) {
defer resetTestEnv()
chat := NewChatCompletion(
WithEndpoint(fmt.Sprintf("test_retry_%d", rand.Intn(100000))),
WithEndpoint(fmt.Sprintf("test_retry_%d", r.Intn(100000))),
WithLLMRetryCount(5),
)
resp, err := chat.Do(
Expand All @@ -218,7 +220,7 @@ func TestChatCompletionRetry(t *testing.T) {
assert.Equal(t, target.Code, InvalidParamErrCode)

chat = NewChatCompletion(
WithEndpoint(fmt.Sprintf("test_retry_%d", rand.Intn(100000))),
WithEndpoint(fmt.Sprintf("test_retry_%d", r.Intn(100000))),
)
_, err = chat.Do(
context.Background(),
Expand All @@ -237,7 +239,7 @@ func TestChatCompletionStreamRetry(t *testing.T) {
GetConfig().LLMRetryCount = 5
defer resetTestEnv()
chat := NewChatCompletion(
WithEndpoint(fmt.Sprintf("test_retry_%d", rand.Intn(100000))),
WithEndpoint(fmt.Sprintf("test_retry_%d", r.Intn(100000))),
)
resp, err := chat.Stream(
context.Background(),
Expand Down Expand Up @@ -268,7 +270,7 @@ func TestChatCompletionStreamRetry(t *testing.T) {
assert.True(t, turn_count > 1)

chat = NewChatCompletion(
WithEndpoint(fmt.Sprintf("test_retry_%d", rand.Intn(100000))),
WithEndpoint(fmt.Sprintf("test_retry_%d", r.Intn(100000))),
WithLLMRetryCount(1),
)
_, err = chat.Stream(
Expand Down Expand Up @@ -636,7 +638,7 @@ func resetModelEndpointRetriever() {
}

func resetTestEnv() {
rand.Seed(time.Now().UnixNano())
r.Seed(time.Now().UnixNano())
logger.SetLevel(logrus.DebugLevel)
os.Setenv("QIANFAN_BASE_URL", "http://127.0.0.1:8866")
os.Setenv("QIANFAN_CONSOLE_BASE_URL", "http://127.0.0.1:8866")
Expand Down
4 changes: 2 additions & 2 deletions python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "qianfan"
version = "0.4.6"
version = "0.4.7"
description = "文心千帆大模型平台 Python SDK"
authors = []
license = "Apache-2.0"
Expand Down Expand Up @@ -62,7 +62,7 @@ uvicorn = { version = ">=0.15.0", optional = true }
filelock = { version = ">=3.7.0", optional = true }

[tool.poetry.scripts]
qianfan = "qianfan.common.client.main:main"
qianfan = "qianfan.common.cli.main:main"

[tool.poetry.group.dev.dependencies]
sphinx = ">=5"
Expand Down
3 changes: 2 additions & 1 deletion python/qianfan/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@
)
from qianfan.utils import disable_log, enable_log
from qianfan.version import VERSION

from qianfan.client import Qianfan

Role = QfRole
Messages = QfMessages
Response = QfResponse

__all__ = [
"Qianfan",
"ChatCompletion",
"Embedding",
"Completion",
Expand Down
17 changes: 17 additions & 0 deletions python/qianfan/client/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright (c) 2024 Baidu, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from qianfan.client.client import Qianfan

__all__ = ["Qianfan"]
96 changes: 96 additions & 0 deletions python/qianfan/client/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Copyright (c) 2024 Baidu, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Any, Optional

from qianfan.config import Config, get_config
from qianfan.consts import DefaultValue
from qianfan.resources import ChatCompletion


class Qianfan:
config: Config

def __init__(
self,
*,
access_key: Optional[str] = None,
secret_key: Optional[str] = None,
api_key: Optional[str] = None,
bearer_token: Optional[str] = None,
app_id: Optional[str] = None,
console_api_base_url: Optional[str] = None,
request_timeout: Optional[int] = None,
retry_count: int = DefaultValue.RetryCount,
**kwargs: Any,
) -> None:
"""
Construct a new qianfan client
This automatically infers the following arguments from their corresponding
environment variables if they are not provided:
- `api_key` from `QIANFAN_BEARER_TOKEN`
- `access_key` from `QIANFAN_ACCESS_KEY`
- `secret_key` from `QIANFAN_SECRET_KEY`
- `app_id` from `QIANFAN_APP_ID`
Args:
access_key (Optional[str], optional): iam access key.
secret_key (Optional[str], optional): iam secret key.
api_key (Optional[str], optional): api_key.
bearer_token (Optional[str], optional): same with api_key.
app_id (Optional[str], optional): qianfan app v2 id.
console_api_base_url (Optional[str], optional): api base url.
"""
if api_key:
bearer_token = api_key
self.config = Config(
ACCESS_KEY=access_key or get_config().ACCESS_KEY,
SECRET_KEY=secret_key or get_config().SECRET_KEY,
BEARER_TOKEN=bearer_token or get_config().BEARER_TOKEN,
APP_ID=app_id or get_config().APP_ID,
CONSOLE_API_BASE_URL=console_api_base_url
or get_config().CONSOLE_API_BASE_URL,
LLM_API_RETRY_COUNT=retry_count or get_config().LLM_API_RETRY_COUNT,
LLM_API_RETRY_TIMEOUT=request_timeout or get_config().LLM_API_RETRY_TIMEOUT,
**kwargs,
)

def __setattr__(self, name: str, value: Any) -> None:
if hasattr(self, name) or name in ["config", "chat", "completions"]:
object.__setattr__(self, name, value)
return
if name == "api_key":
self.config.BEARER_TOKEN = value
return
self.config.__setattr__(name, value)

@property
def chat(self) -> "Chat":
return Chat(self)

@property
def completions(self) -> "ChatCompletion":
return ChatCompletion(config=self.config, version=2)


class Chat:
_client: Qianfan

def __init__(self, client: "Qianfan") -> None:
self._client = client

@property
def completions(self) -> ChatCompletion:
return ChatCompletion(config=self._client.config, version=2)
4 changes: 3 additions & 1 deletion python/qianfan/common/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from qianfan.common import cli
from qianfan.common.prompt.prompt import Prompt, PromptLabel

__all__ = ["Prompt", "PromptLabel"]
client = cli
__all__ = ["Prompt", "PromptLabel", "cli"]
File renamed without changes.
66 changes: 66 additions & 0 deletions python/qianfan/common/cli/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Copyright (c) 2024 Baidu, Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import json
import time

import typer

from qianfan import resources
from qianfan.common.cli.utils import (
credential_required,
)
from qianfan.resources.console.utils import call_action

api_app = typer.Typer(
no_args_is_help=True,
help="Qianfan api",
context_settings={"help_option_names": ["-h", "--help"]},
)


@api_app.command(name="finetune.task.detail")
@credential_required
def task_info(
task_id: str = typer.Option(..., help="task id"),
) -> None:
"""
get a finetune task info from local cache
"""
resp = resources.FineTune.V2.task_detail(task_id=task_id)
json_str = json.dumps(resp.body, ensure_ascii=False, indent=2)
print(json_str)

# wait a second for the log to be flushed
time.sleep(0.1)


@api_app.command(name="raw.console")
@credential_required
def call_console(
route: str = typer.Option(..., help="route, e.g. /v2/finetuning"),
action: str = typer.Option(..., help="action, e.g. DescribeFineTuningTask"),
data: str = typer.Option(..., help="req body"),
) -> None:
"""
create a console action api call
"""
d = json.loads(data)
assert isinstance(d, dict)
resp = call_action(base_url_route=route, action=action, params=d)
json_str = json.dumps(resp.body, ensure_ascii=False, indent=2)
print(json_str)

# wait a second for the log to be flushed
time.sleep(0.1)
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from rich.text import Text

from qianfan import QfRole
from qianfan.common.client.utils import (
from qianfan.common.cli.utils import (
InputEmptyValidator,
credential_required,
list_model_option,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

import qianfan
from qianfan import Messages, QfResponse, QfRole
from qianfan.common.client.utils import (
from qianfan.common.cli.utils import (
create_client,
credential_required,
list_model_option,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@
from rich.rule import Rule
from rich.table import Table

import qianfan.common.client.utils as client_utils
from qianfan.common.client.utils import (
import qianfan.common.cli.utils as client_utils
from qianfan.common.cli.utils import (
check_credential,
credential_required,
enum_typer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from qianfan.common.client.utils import (
from qianfan.common.cli.utils import (
list_model_option,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
from rich.pretty import Pretty
from rich.table import Table

from qianfan.common.client.dataset import load_dataset
from qianfan.common.client.utils import (
from qianfan.common.cli.dataset import load_dataset
from qianfan.common.cli.utils import (
credential_required,
print_error_msg,
print_info_msg,
Expand Down
Loading

0 comments on commit 2c90822

Please sign in to comment.