This repository was archived by the owner on Apr 24, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 519
/
Copy pathcore.py
133 lines (122 loc) · 4.95 KB
/
core.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import os
import random
import string
import requests
import json
import re
class Bard:
HEADERS = {
"Host": "bard.google.com",
"X-Same-Domain": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36",
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
"Origin": "https://bard.google.com",
"Referer": "https://bard.google.com/",
}
def __init__(
self,
token: str = None,
timeout: int = 20,
proxies: dict = None,
session: requests.Session = None,
):
"""
Initialize Bard
:param token: (`str`, *optional*)
__Secure-1PSID value. default to os.getenv("_BARD_API_KEY")
:param timeout: (`int`, *optional*)
Timeout in seconds when connecting bard server. The timeout is used on each request.
:param proxies: (`Dict[str, str]`, *optional*)
A dictionary of proxy servers to use by protocol or endpoint, e.g., `{'http': 'foo.bar:3128',
'http://hostname': 'foo.bar:4012'}`. The proxies are used on each request.
:param session: (`requests.Session`, *optional*)
An existing requests.Session object to be used for making HTTP requests.
"""
self.token = token or os.getenv("_BARD_API_KEY")
self.proxies = proxies
self.timeout = timeout
self._reqid = int("".join(random.choices(string.digits, k=4)))
self.conversation_id = ""
self.response_id = ""
self.choice_id = ""
self.session = session or requests.Session()
self.session.headers = self.HEADERS
self.session.cookies.set("__Secure-1PSID", self.token)
self.SNlM0e = self._get_snim0e()
def _get_snim0e(self):
if not self.token or self.token[-1] != ".":
raise Exception(
"__Secure-1PSID value must end with a single dot. Enter correct __Secure-1PSID value."
)
resp = self.session.get(
"https://bard.google.com/", timeout=self.timeout, proxies=self.proxies
)
if resp.status_code != 200:
raise Exception(
f"Response code not 200. Response Status is {resp.status_code}"
)
snim0e = re.search(r"SNlM0e\":\"(.*?)\"", resp.text)
if not snim0e:
raise Exception(
"SNlM0e value not found in response. Check __Secure-1PSID value."
)
return snim0e.group(1)
def get_answer(self, input_text: str) -> dict:
"""
Get the answer from Bard based on the input text.
Example:
>>> token = 'xxxxxxxxxx'
>>> bard = Bard(token=token)
>>> response = bard.get_answer("나와 내 동년배들이 좋아하는 뉴진스에 대해서 알려줘")
>>> print(response['content'])
:param input_text: (`str`)
The input text for which the answer is requested.
:return: (`dict`)
The dictionary containing the response from Bard with the following keys:
- "content": The content of the answer.
- "conversation_id": The conversation ID.
- "response_id": The response ID.
- "factualityQueries": Factuality queries (if any).
- "textQuery": The text query used for the answer.
- "choices": The choices available (if any).
"""
params = {
"bl": "boq_assistant-bard-web-server_20230419.00_p1",
"_reqid": str(self._reqid),
"rt": "c",
}
input_text_struct = [
[input_text],
None,
[self.conversation_id, self.response_id, self.choice_id],
]
data = {
"f.req": json.dumps([None, json.dumps(input_text_struct)]),
"at": self.SNlM0e,
}
resp = self.session.post(
"https://bard.google.com/_/BardChatUi/data/assistant.lamda.BardFrontendService/StreamGenerate",
params=params,
data=data,
timeout=self.timeout,
proxies=self.proxies,
)
resp_dict = json.loads(resp.content.splitlines()[3])[0][2]
if not resp_dict:
return {"content": f"Response Error: {resp.content}."}
parsed_answer = json.loads(resp_dict)
bard_answer = {
"content": parsed_answer[0][0],
"conversation_id": parsed_answer[1][0],
"response_id": parsed_answer[1][1],
"factualityQueries": parsed_answer[3],
"textQuery": parsed_answer[2][0] if parsed_answer[2] else "",
"choices": [{"id": i[0], "content": i[1]} for i in parsed_answer[4]],
}
self.conversation_id, self.response_id, self.choice_id = (
bard_answer["conversation_id"],
bard_answer["response_id"],
bard_answer["choices"][0]["id"],
)
self._reqid += 100000
return bard_answer