Skip to content

Commit

Permalink
impr: improve document
Browse files Browse the repository at this point in the history
  • Loading branch information
ultrasev committed Apr 12, 2024
1 parent d422ab4 commit ac0758b
Show file tree
Hide file tree
Showing 6 changed files with 64 additions and 15 deletions.
3 changes: 1 addition & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ RUN pip install poetry
COPY pyproject.toml /app/
COPY chatrapper/ /app/chatrapper/

RUN poetry config virtualenvs.create false
RUN poetry install --no-dev
RUN poetry install --only main

EXPOSE 9000

Expand Down
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
IMAGE_NAME=chatrapper

build:
docker build -t $(IMAGE_NAME) .

run:
docker run -it --rm -p 9000:9000 $(IMAGE_NAME)

test:
poetry run pytest -vv
40 changes: 29 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,47 @@
<a href='https://follow-your-click.github.io/'><img src='https://img.shields.io/badge/Project-Page-Green'></a> ![visitors](https://visitor-badge.laobi.icu/badge?page_id=ultrasev.chatrapper&left_color=green&right_color=red) [![GitHub](https://img.shields.io/github/stars/ultrasev/chatrapper?style=social)](https://github.com/ultrasev/chatrapper)
</div>

把网页版 ChatGPT 封装为一个 API,以便在代码中使用
免登录版 ChatGPT web API 的 Python 封装,支持本地安装和 Docker 部署。兼容 OpenAI 的 API 规范,支持 ChatGPT-3.5 模型

# 本地安装
```bash
pip3 install git+https://github.com/ultrasev/chatrapper.git
```

# 代码中直接使用
在代码中使用 `Rapper`:
在代码中使用同步版 `Rapper`:
```python
import os
from chatrapper import Rapper
rapper = Rapper()
rapper("鲁迅为什么打周树人?")
rapper = Rapper(stream=False)
print(rapper("鲁迅为什么打周树人?"))
```

或者有异步需求的话,可以使用 `AsyncRapper`。这种情况下,最好有多个账号支持,单账号下,同一时间只支持一轮对话。
Response:
```text
鲁迅和周树人之间的矛盾源于他们在文学理念、文学风格以及政治立场上的分歧。周树人是新文化运动的重要人物之一,与鲁迅一样,他也是一位重要的文学家和思想家。然而,两人在一些关键问题上存在分歧。
...
```

也可以通过列表传入多轮对话的历史记录。

```python
from chatrapper import Rapper
rapper = Rapper(stream=False)
messages = [
{"role": "system", "content": "You are a poetic assistant, skilled in explaining complex programming concepts with creative flair."},
{"role": "user", "content": "Compose a poem that explains the concept of recursion in programming."}
]
print(rapper(messages))
```

异步需求场景下,可以使用 `AsyncRapper`

```python
import os
import asyncio
from chatrapper import AsyncRapper
rapper = AsyncRapper()

async def main():
print(await rapper("鲁迅为什么打周树人?"))
return await AsyncRapper(stream=True)("what is the purpose of life?")

asyncio.run(main())
```
Expand All @@ -45,7 +61,7 @@ Demo:

# Docker 部署
```bash
docker run --name chatrapper -p 9000:9000 ghcr.io/ultrasev/chatrapper
docker run --name rapper -p 9000:9000 ghcr.io/ultrasev/chatrapper
```

请求示例:
Expand All @@ -66,7 +82,9 @@ curl http://127.0.0.1:9000/v1/chat/completions \
```

# Notes
- 合理使用 API,调用频率不宜过高,树大易招风,避免触发风控。
- 部署服务不挑 IP,但建议优先使用带美区 IP 的服务器。
- 合理使用 API,调用频率不宜过高。树大易招风,避免触发风控。

# TODO
- [ ] 结合 access_token 支持 GPT-4(需要登录且开通 premium)。
- [ ] 支持 OpenAI API chat 接口。
2 changes: 1 addition & 1 deletion chatrapper/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ async def stream(self, inputx: typing.Union[str, typing.List[typing.Dict]]) -> t
'POST',
url=f"{BASE_URL}/backend-api/conversation",
headers=headers,
data=json.dumps(body)
content=json.dumps(body)
) as response:
async for chunk in response.aiter_text():
chunk = chunk.lstrip("data: ").strip()
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "chatrapper"
version = "0.1.0"
version = "0.1.1"
description = ""
authors = ["ultrasev <i@ultrasev.com>"]
readme = "README.md"
Expand Down
22 changes: 22 additions & 0 deletions tests/test_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env python
import pytest

from chatrapper import AsyncRapper, Rapper, ReqHeader


def test_header():
rh = ReqHeader(**{"hello": "world"})
assert isinstance(dict(ReqHeader()), dict)


@pytest.mark.asyncio
async def test_async_rapper_working():
answer = await AsyncRapper(stream=False
)("What is the capital of the United States?")
assert "Washington" in answer


@pytest.mark.asyncio
async def test_get_ession_id():
session_id = await AsyncRapper().get_new_session_id()
assert session_id is not None

0 comments on commit ac0758b

Please sign in to comment.