phisinger commited on
Commit
7910a4d
1 Parent(s): 7c99e3e

initial commit

Browse files
README.md CHANGED
@@ -4,7 +4,7 @@ emoji: 😻
4
  colorFrom: green
5
  colorTo: indigo
6
  sdk: gradio
7
- sdk_version: 4.14.0
8
  app_file: app.py
9
  pinned: false
10
  license: apache-2.0
 
4
  colorFrom: green
5
  colorTo: indigo
6
  sdk: gradio
7
+ sdk_version: 4.12.0
8
  app_file: app.py
9
  pinned: false
10
  license: apache-2.0
Vectorstore.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain.embeddings import GPT4AllEmbeddings
2
+ from langchain.document_loaders import TextLoader, DirectoryLoader
3
+ from langchain.text_splitter import RecursiveCharacterTextSplitter
4
+ from langchain.embeddings import GPT4AllEmbeddings
5
+ from langchain.vectorstores import Chroma
6
+ import chromadb
7
+
8
+
9
+ class Vectorstore_client:
10
+ def __init__(self):
11
+ self.persist_directory = "/home/phisinger/Programmieren/wahlprogramm_analyse/data/vectorstore"
12
+ self.client = chromadb.PersistentClient(path=self.persist_directory)
13
+ elections = ["2013", "2017", "2021"]
14
+ for election in elections:
15
+ # load all files from cleaned data set
16
+ glob = "*" + election + ".txt"
17
+ loader = DirectoryLoader(
18
+ '/home/phisinger/Programmieren/wahlprogramm_analyse/data/clean/', glob=glob, use_multithreading=True, loader_cls=TextLoader)
19
+ docs_list = loader.load()
20
+ # split documents
21
+ text_splitter = RecursiveCharacterTextSplitter(
22
+ chunk_size=1000, chunk_overlap=200)
23
+ all_splits = text_splitter.split_documents(docs_list)
24
+ all_texts = [text.page_content for text in all_splits]
25
+ # generate ids for all documents
26
+ ids_list = ["id{}".format(i)
27
+ for i in range(1, len(all_texts) + 1)]
28
+ # Store splits in database
29
+ collection = self.client.get_or_create_collection(
30
+ name=election)
31
+ if collection.count() == 0:
32
+ collection.add(
33
+ documents=all_texts,
34
+ ids=ids_list
35
+ )
36
+ return
37
+
38
+ def get_client(self):
39
+ return self.client
40
+
41
+
42
+ # class Vectorstore:
43
+ # def __init__(self) -> None:
44
+ # self.persist_directory = "/home/phisinger/Programmieren/wahlprogramm_analyse/data/vectorstore"
45
+ # if False:
46
+ # # load data from data persist_directory
47
+ # print("use persisted db.")
48
+ # self.vectordb = Chroma(persist_directory=persist_directory,
49
+ # embedding_function=GPT4AllEmbeddings())
50
+ # else:
51
+ # print("Build new vector DB")
52
+ # self.build_vectorstore()
53
+
54
+ # return self.vectordb
55
+
56
+ # def build_vectorstore(self):
57
+ # elections = ["2013", "2017", "2021"]
58
+ # for election in elections:
59
+ # # load all files from cleaned data set
60
+ # glob = "*" + election + ".txt"
61
+ # loader = DirectoryLoader(
62
+ # '../data/clean/', glob=glob, use_multithreading=True, loader_cls=TextLoader)
63
+ # docs_list = loader.load()
64
+ # # split documents
65
+ # text_splitter = RecursiveCharacterTextSplitter(
66
+ # chunk_size=1000, chunk_overlap=200)
67
+ # all_splits = text_splitter.split_documents(docs_list)
68
+ # # store documents in vector store
69
+ # self.vectordb = Chroma.from_documents(
70
+ # documents=all_splits, embedding=GPT4AllEmbeddings(), persist_directory=self.persist_directory)
71
+ # self.vectordb.persist()
72
+
73
+ # def get(self):
74
+ # return self.vectordb
app.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from langchain.prompts import PromptTemplate
2
+ from langchain.chains import RetrievalQA
3
+ from langchain.embeddings import GPT4AllEmbeddings
4
+ from langchain.vectorstores import Chroma
5
+ from Vectorstore import Vectorstore_client
6
+ import gradio as gr
7
+
8
+ # Load Model
9
+ from langchain.llms import GPT4All
10
+
11
+ llm = GPT4All(
12
+ model="/home/phisinger/Programmieren/wahlprogramm_analyse/models/mistral-7b-openorca.Q4_0.gguf",
13
+ max_tokens=2048,
14
+ )
15
+
16
+ # establish connection to vector store chroma
17
+ db_client = Vectorstore_client()
18
+ db_client = db_client.get_client()
19
+
20
+
21
+ collection_name = ""
22
+
23
+
24
+ with gr.Blocks() as demo:
25
+ gr.Markdown("# Election Program Chatbot")
26
+
27
+ def set_collection(year):
28
+ global collection_name
29
+ collection_name = year
30
+ # Dropdown to select the year to ask
31
+ gr.Interface(
32
+ fn=set_collection,
33
+ inputs=gr.Dropdown(
34
+ ["2013", "2017", "2021"], label="Election Year", info="Select the election year you want to chat with"),
35
+ outputs=None,
36
+ )
37
+
38
+ # Explain chatbot
39
+ gr.Markdown(
40
+ """The chatbot has access to all election programs of the selected year. You may ask questions in German. As this is a demo, you should be warned that the generation can take several minutes (up to 600 secs). <br/>
41
+ Be also aware that the chatbot doesn't take into account the history of the chat. It answers every question independently.""")
42
+
43
+ def generate_answer(message, history):
44
+ global collection_name
45
+ if collection_name == "":
46
+ gr.Warning(
47
+ "No election year is selected! The default year '2021' is used.")
48
+ collection_name = "2021"
49
+ # integrate vector store into langchain chroma version
50
+ langchain_chroma = Chroma(
51
+ client=db_client,
52
+ collection_name=collection_name,
53
+ embedding_function=GPT4AllEmbeddings(),
54
+ )
55
+
56
+ # Prepare chain to ask questions
57
+ # german default prompt
58
+ german_prompt = """Beantworten Sie die Frage am Ende des Textes anhand der folgenden Informationen. Wenn Sie die Antwort nicht wissen, sagen Sie einfach, dass Sie es nicht wissen, versuchen Sie nicht, eine Antwort zu erfinden.
59
+
60
+ {context}
61
+
62
+ Frage: {question}
63
+ Hilfreiche Antwort:"""
64
+ german_prompt = PromptTemplate(
65
+ template=german_prompt, input_variables=["context", "question"]
66
+ )
67
+
68
+ # TODO: Make Prompt for Wahlomat-like usage
69
+
70
+ # create Q & A chain for the chatbot
71
+ qa_chain = RetrievalQA.from_chain_type(
72
+ llm,
73
+ retriever=langchain_chroma.as_retriever(),
74
+ chain_type_kwargs={"prompt": german_prompt},
75
+ )
76
+
77
+ return qa_chain({"query": message})["result"]
78
+ gr.ChatInterface(generate_answer)
79
+
80
+
81
+ demo.launch()
data/clean/afd_2013.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ wahlprogramm parteitagsbeschluss vom 14.04.2013 währungspolitik wir fordern eine geordnete auflösung des euro-währungsgebietes. deutschland braucht den euro nicht. anderen ländern schadet der euro. wir fordern die wiedereinführung nationaler währungen oder die schaffung kleinerer und stabilerer währungsverbünde. die wiedereinführung der dm darf kein tabu sein. wir fordern eine änderung der europäischen verträge, um jedem staat ein ausscheiden aus dem euro zu ermöglichen. jedes volk muss demokratisch über seine währung entscheiden dürfen. wir fordern, dass deutschland dieses austrittsrecht aus dem euro erzwingt, indem es weitere hilfskredite des esm mit seinem veto blockiert. wir fordern, dass die kosten der sogenannten rettungs-politik nicht vom steuerzahler getragen werden. banken, hedge-fonds und private großanleger sind die nutznießer dieser politik. sie müssen zuerst dafür geradestehen. wir fordern, dass hoffnungslos überschuldete staaten durch einen schuldenschnitt entschuldet werden. in der schuldenkrise müssen banken ihre verluste selbst tragen oder zu lasten ihrer privaten großgläubiger stabilisiert werden. wir fordern ein sofortiges verbot des ankaufs von schrottpapieren durch die europäische zentralbank. inflation darf nicht die ersparnisse der bürger aufzehren. europapolitik wir bejahen ein europa souveräner staaten mit einem gemeinsamen binnenmarkt. wir wollen in freundschaft und guter wir werden dafür sorgen, dass gesetzgebungskompetenzen zurück zu den nationalen parlamenten verlagert werden. wir werden uns für eine reform der eu stark machen, um die brüssele bürokratie abzubauen und transparenz und bürgernähe zu fördern. das europäische parlament hat bei der kontrolle brüssels versagt. wir unterstützen nachdrücklich die positionen david camerons, die eu durch mehr wettbewerb und eigenverantwortung zu verschlanken. rechtsstaatlichkeit und demokratie wir fordern, den rechtsstaat uneingeschränkt zu achten. staatliche organe dürfen sich selbst in einzelfällen nicht über gesetze und verträge hinwegsetzen. vielmehr sind diese nach ihrem buchstaben und nach ihrem geist zu respektieren. das handeln jeder deutschen regierung findet seine beschränkungen im völkerrecht, im grundgesetz und in den europäischen verträgen. diese sind für unsere gesellschaft von fundamentaler bedeutung und strikt zu befolgen. wir fordern eine stärkung der demokratie und der demokratischen bürgerrechte. wir wollen volksabstimmungen und -initiativen nach schweizer vorbild einführen. das gilt insbesondere für die abtretung wichtiger befugnisse an die eu. parteien sollen am politischen system mitwirken, es aber nicht beherrschen. wir fordern mehr direkte demokratie auch in den parteien. das volk soll den willen der parteien bestimmen, nicht umgekehrt. wir fordern, dass bundestagsabgeordnete ihre volle arbeitskraft der parlamentarischen arbeit widmen. das mandat darf nicht unter bezahlten nebentätigkeiten leiden. wir setzen uns dafür ein, dass auch unkonventionelle meinungen im öffentlichen diskurs ergebnisoffen diskutiert werden, solange die meinungen nicht gegen die werte des grundgesetzes verstoßen. staatsfinanzen und steuern wir fordern, die schuldenbremse zu achten und die schuldenberge abzubauen. auch deutschland hat viel mehr schulden als zulässig. wir fordern, dass die haftungsrisiken aus der euro-rettungs-politik endlich in der finanzplanung berücksichtigt werden. derzeit wird den bürgern bewusst sand in die augen gestreut. wir fordern eine drastische vereinfachung des steuerrechts in anlehnung an das progressiv wirkende kirchhofsche steuermodell. der bürger muss verstehen können, warum er in welcher höhe besteuert wird. alterssicherung und familie die eurokrise gefährdet alle formen der altersvorsorge durch überschuldung und minimale zinsen. die schulden der eurokrise dürfen nicht zu einer rente nach kassenlage führen. wir fordern, kinder stärker bei der rentenberechnung zu berücksichtigen. deutschland hat zu wenige kinder. renten- und krankenversicherung stehen deshalb auf tönernen füßen. deutschland muss kinder- und familienfreundlicher werden. wir stehen für den schutz der familie als keimzelle der gesellschaft. eine solidarische förderung der familien ist eine investition in unsere gemeinsame zukunft und wesentlicher teil des generationenvertrages. bildung wir fordern bundesweit einheitliche bildungsstandards orientiert an den besten schulsystemen deutschlands. wir fordern, bildung als kernaufgabe der familie zu fördern. kitas und schulen müssen dies sinnvoll ergänzen. nichts ist für unsere zukunft wichtiger als die bildung unserer kinder. wir fordern ein qualitativ hochwertiges universitätssystem, das den studenten angemessene betreuungs- und fördermöglichkeiten bietet. auch eine rückkehr zu bewährten diplom- und staatsexamensstudiengängen muss möglich sein. energiepolitik wir fordern ein nachhaltiges energiekonzept für bezahlbare energie. es ist unzumutbar, dass die bevölkerung mit drastisch steigenden preisen für die kopf- und konzeptionslose politik der bundesregierung büßen muss. wir fordern eine reform des erneuerbaren-energien-gesetzes (eeg). es ist unsozial, subventionen für sonnen- und windenergie durch die strompreise zu finanzieren. wir fordern, dass subventionen für erneuerbare energien stattdessen aus dem allgemeinen steueraufkommen finanziert werden. es muss offengelegt werden, welche energieart wie stark subventioniert wird. integrationspolitik wir fordern eine neuordnung des einwanderungsrechts. deutschland braucht qualifizierte und integrationswillige zuwanderung. wir fordern ein einwanderungsgesetz nach kanadischem vorbild. eine ungeordnete zuwanderung in unsere sozialsysteme muss unbedingt unterbunden werden. ernsthaft politisch verfolgte müssen in deutschland asyl finden können. zu einer menschenwürdigen behandlung gehört auch, dass asylbewerber hier arbeiten können.
data/clean/afd_2017.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/afd_2021.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/cdu_2013.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/cdu_2017.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/cdu_2021.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/fdp_2013.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/fdp_2017.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/fdp_2021.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/gruene_2013.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/gruene_2017.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/gruene_2021.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/linke_2013.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/linke_2017.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/linke_2021.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/spd_2013.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/spd_2017.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/clean/spd_2021.txt ADDED
The diff for this file is too large to render. See raw diff
 
requirements.txt ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==23.2.1
2
+ aiohttp==3.9.1
3
+ aiosignal==1.3.1
4
+ altair==5.2.0
5
+ annotated-types==0.6.0
6
+ anyio==3.7.1
7
+ asgiref==3.7.2
8
+ asttokens @ file:///home/conda/feedstock_root/build_artifacts/asttokens_1698341106958/work
9
+ async-timeout==4.0.3
10
+ attrs==23.1.0
11
+ backoff==2.2.1
12
+ bcrypt==4.1.2
13
+ cachetools==5.3.2
14
+ certifi==2023.11.17
15
+ charset-normalizer==3.3.2
16
+ chroma-hnswlib==0.7.3
17
+ chromadb==0.4.21
18
+ click==8.1.7
19
+ colorama==0.4.6
20
+ coloredlogs==15.0.1
21
+ comm @ file:///home/conda/feedstock_root/build_artifacts/comm_1691044910542/work
22
+ contourpy==1.2.0
23
+ cycler==0.12.1
24
+ dataclasses-json==0.6.3
25
+ debugpy @ file:///croot/debugpy_1690905042057/work
26
+ decorator @ file:///home/conda/feedstock_root/build_artifacts/decorator_1641555617451/work
27
+ Deprecated==1.2.14
28
+ entrypoints @ file:///home/conda/feedstock_root/build_artifacts/entrypoints_1643888246732/work
29
+ exceptiongroup @ file:///home/conda/feedstock_root/build_artifacts/exceptiongroup_1700579780973/work
30
+ executing @ file:///home/conda/feedstock_root/build_artifacts/executing_1698579936712/work
31
+ fastapi==0.106.0
32
+ ffmpy==0.3.1
33
+ filelock==3.13.1
34
+ flatbuffers==23.5.26
35
+ fonttools==4.47.0
36
+ frozenlist==1.4.1
37
+ fsspec==2023.12.2
38
+ google-auth==2.25.2
39
+ googleapis-common-protos==1.62.0
40
+ gpt4all==2.0.2
41
+ gradio_client==0.8.0
42
+ greenlet==3.0.3
43
+ grpcio==1.60.0
44
+ h11==0.14.0
45
+ httpcore==1.0.2
46
+ httptools==0.6.1
47
+ httpx==0.26.0
48
+ huggingface-hub==0.20.1
49
+ humanfriendly==10.0
50
+ idna==3.6
51
+ importlib-metadata==6.11.0
52
+ importlib-resources==6.1.1
53
+ ipykernel @ file:///home/conda/feedstock_root/build_artifacts/ipykernel_1703631723894/work
54
+ ipython @ file:///home/conda/feedstock_root/build_artifacts/ipython_1703263236586/work
55
+ jedi @ file:///home/conda/feedstock_root/build_artifacts/jedi_1696326070614/work
56
+ Jinja2==3.1.2
57
+ jsonpatch==1.33
58
+ jsonpointer==2.4
59
+ jsonschema==4.20.0
60
+ jsonschema-specifications==2023.12.1
61
+ jupyter-client @ file:///home/conda/feedstock_root/build_artifacts/jupyter_client_1654730843242/work
62
+ jupyter_core @ file:///home/conda/feedstock_root/build_artifacts/jupyter_core_1703611850573/work
63
+ kiwisolver==1.4.5
64
+ kubernetes==28.1.0
65
+ langchain==0.0.352
66
+ langchain-community==0.0.6
67
+ langchain-core==0.1.3
68
+ langchainhub==0.1.14
69
+ langsmith==0.0.75
70
+ markdown-it-py==3.0.0
71
+ MarkupSafe==2.1.3
72
+ marshmallow==3.20.1
73
+ matplotlib==3.8.2
74
+ matplotlib-inline @ file:///home/conda/feedstock_root/build_artifacts/matplotlib-inline_1660814786464/work
75
+ mdurl==0.1.2
76
+ mmh3==4.0.1
77
+ monotonic==1.6
78
+ mpmath==1.3.0
79
+ multidict==6.0.4
80
+ mypy-extensions==1.0.0
81
+ nest-asyncio @ file:///home/conda/feedstock_root/build_artifacts/nest-asyncio_1697083700168/work
82
+ numpy==1.26.2
83
+ oauthlib==3.2.2
84
+ onnxruntime==1.16.3
85
+ opentelemetry-api==1.22.0
86
+ opentelemetry-exporter-otlp-proto-common==1.22.0
87
+ opentelemetry-exporter-otlp-proto-grpc==1.22.0
88
+ opentelemetry-instrumentation==0.43b0
89
+ opentelemetry-instrumentation-asgi==0.43b0
90
+ opentelemetry-instrumentation-fastapi==0.43b0
91
+ opentelemetry-proto==1.22.0
92
+ opentelemetry-sdk==1.22.0
93
+ opentelemetry-semantic-conventions==0.43b0
94
+ opentelemetry-util-http==0.43b0
95
+ orjson==3.9.10
96
+ overrides==7.4.0
97
+ packaging @ file:///home/conda/feedstock_root/build_artifacts/packaging_1696202382185/work
98
+ pandas==2.1.4
99
+ parso @ file:///home/conda/feedstock_root/build_artifacts/parso_1638334955874/work
100
+ pexpect @ file:///home/conda/feedstock_root/build_artifacts/pexpect_1667297516076/work
101
+ pickleshare @ file:///home/conda/feedstock_root/build_artifacts/pickleshare_1602536217715/work
102
+ Pillow==10.1.0
103
+ platformdirs @ file:///home/conda/feedstock_root/build_artifacts/platformdirs_1701708255999/work
104
+ posthog==3.1.0
105
+ prompt-toolkit @ file:///home/conda/feedstock_root/build_artifacts/prompt-toolkit_1702399386289/work
106
+ protobuf==4.25.1
107
+ psutil @ file:///opt/conda/conda-bld/psutil_1656431268089/work
108
+ ptyprocess @ file:///home/conda/feedstock_root/build_artifacts/ptyprocess_1609419310487/work/dist/ptyprocess-0.7.0-py2.py3-none-any.whl
109
+ pulsar-client==3.3.0
110
+ pure-eval @ file:///home/conda/feedstock_root/build_artifacts/pure_eval_1642875951954/work
111
+ pyasn1==0.5.1
112
+ pyasn1-modules==0.3.0
113
+ pydantic==2.5.3
114
+ pydantic_core==2.14.6
115
+ pydub==0.25.1
116
+ Pygments @ file:///home/conda/feedstock_root/build_artifacts/pygments_1700607939962/work
117
+ pyparsing==3.1.1
118
+ PyPika==0.48.9
119
+ python-dateutil @ file:///home/conda/feedstock_root/build_artifacts/python-dateutil_1626286286081/work
120
+ python-dotenv==1.0.0
121
+ python-multipart==0.0.6
122
+ pytz==2023.3.post1
123
+ PyYAML==6.0.1
124
+ pyzmq @ file:///croot/pyzmq_1686601365461/work
125
+ referencing==0.32.0
126
+ requests==2.31.0
127
+ requests-oauthlib==1.3.1
128
+ rich==13.7.0
129
+ rpds-py==0.16.2
130
+ rsa==4.9
131
+ semantic-version==2.10.0
132
+ shellingham==1.5.4
133
+ six @ file:///home/conda/feedstock_root/build_artifacts/six_1620240208055/work
134
+ sniffio==1.3.0
135
+ SQLAlchemy==2.0.24
136
+ stack-data @ file:///home/conda/feedstock_root/build_artifacts/stack_data_1669632077133/work
137
+ starlette==0.27.0
138
+ sympy==1.12
139
+ tenacity==8.2.3
140
+ tokenizers==0.15.0
141
+ tomlkit==0.12.0
142
+ toolz==0.12.0
143
+ tornado @ file:///home/conda/feedstock_root/build_artifacts/tornado_1648827254365/work
144
+ tqdm==4.66.1
145
+ traitlets @ file:///home/conda/feedstock_root/build_artifacts/traitlets_1701095650114/work
146
+ typer==0.9.0
147
+ types-requests==2.31.0.6
148
+ types-urllib3==1.26.25.14
149
+ typing-inspect==0.9.0
150
+ typing_extensions @ file:///home/conda/feedstock_root/build_artifacts/typing_extensions_1702176139754/work
151
+ tzdata==2023.4
152
+ urllib3==1.26.18
153
+ uvicorn==0.25.0
154
+ uvloop==0.19.0
155
+ watchfiles==0.21.0
156
+ wcwidth @ file:///home/conda/feedstock_root/build_artifacts/wcwidth_1700607916581/work
157
+ websocket-client==1.7.0
158
+ websockets==11.0.3
159
+ wrapt==1.16.0
160
+ yarl==1.9.4
161
+ zipp==3.17.0