QWEN Chat model for free
Browse files- .gitignore +97 -0
- QWEN/__init__.py +144 -0
- README.md +19 -0
- install.sh +50 -0
- query.py +31 -0
- requirements.txt +6 -0
- run.sh +18 -0
.gitignore
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# skin_color
|
2 |
+
.ipynb_checkpoints
|
3 |
+
__pycache__/
|
4 |
+
tmp/
|
5 |
+
flask_session/
|
6 |
+
*.sarif
|
7 |
+
*.xlsx
|
8 |
+
*.h5
|
9 |
+
|
10 |
+
# Byte-compiled / optimized / DLL files
|
11 |
+
__pycache__/
|
12 |
+
*.py[cod]
|
13 |
+
*$py.class
|
14 |
+
|
15 |
+
*.DS_Store
|
16 |
+
|
17 |
+
# Distribution / packaging
|
18 |
+
.Python
|
19 |
+
build/
|
20 |
+
develop-eggs/
|
21 |
+
dist/
|
22 |
+
downloads/
|
23 |
+
eggs/
|
24 |
+
.eggs/
|
25 |
+
lib/
|
26 |
+
lib64/
|
27 |
+
parts/
|
28 |
+
sdist/
|
29 |
+
var/
|
30 |
+
wheels/
|
31 |
+
*.egg-info/
|
32 |
+
.installed.cfg
|
33 |
+
*.egg
|
34 |
+
MANIFEST
|
35 |
+
|
36 |
+
# Installer logs
|
37 |
+
pip-log.txt
|
38 |
+
pip-delete-this-directory.txt
|
39 |
+
|
40 |
+
# Unit test / coverage reports
|
41 |
+
htmlcov/
|
42 |
+
.tox/
|
43 |
+
.coverage
|
44 |
+
.coverage.*
|
45 |
+
.cache
|
46 |
+
nosetests.xml
|
47 |
+
coverage.xml
|
48 |
+
*.cover
|
49 |
+
.hypothesis/
|
50 |
+
.pytest_cache/
|
51 |
+
|
52 |
+
# Sphinx documentation
|
53 |
+
docs/_build/
|
54 |
+
|
55 |
+
# PyBuilder
|
56 |
+
target/
|
57 |
+
|
58 |
+
# Jupyter Notebook
|
59 |
+
.ipynb_checkpoints
|
60 |
+
|
61 |
+
# pyenv
|
62 |
+
.python-version
|
63 |
+
|
64 |
+
# PyTorch weights
|
65 |
+
*.tar
|
66 |
+
*.pth
|
67 |
+
*.pt
|
68 |
+
*.torch
|
69 |
+
*.gz
|
70 |
+
Untitled.ipynb
|
71 |
+
Testing notebook.ipynb
|
72 |
+
|
73 |
+
# Root dir exclusions
|
74 |
+
/*.csv
|
75 |
+
/*.yaml
|
76 |
+
/*.json
|
77 |
+
/*.jpg
|
78 |
+
/*.png
|
79 |
+
/*.zip
|
80 |
+
/*.tar.*
|
81 |
+
*.jpg
|
82 |
+
*.png
|
83 |
+
*.avi
|
84 |
+
*.mp4
|
85 |
+
*.svg
|
86 |
+
|
87 |
+
.mypy_cache/
|
88 |
+
.vscode/
|
89 |
+
.idea
|
90 |
+
|
91 |
+
output/
|
92 |
+
input/
|
93 |
+
|
94 |
+
!test/*
|
95 |
+
|
96 |
+
node_modules/
|
97 |
+
package-lock.json
|
QWEN/__init__.py
ADDED
@@ -0,0 +1,144 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import Optional, List, Any, Dict, Iterator
|
2 |
+
from langchain_core.language_models import BaseChatModel
|
3 |
+
from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, SystemMessage
|
4 |
+
from langchain_core.outputs import ChatGeneration, ChatResult
|
5 |
+
from pydantic import PrivateAttr
|
6 |
+
|
7 |
+
# used for qwen inference
|
8 |
+
import torch
|
9 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
10 |
+
|
11 |
+
|
12 |
+
class ChatQWEN(BaseChatModel):
|
13 |
+
"""A custom chat model that invoke Qwen2.5-1.5B-Instruct.
|
14 |
+
|
15 |
+
Example:
|
16 |
+
|
17 |
+
.. code-block:: python
|
18 |
+
|
19 |
+
model = ChatQWEN()
|
20 |
+
result = model.invoke([HumanMessage(content="hello")])
|
21 |
+
result = model.batch([[HumanMessage(content="hello")],
|
22 |
+
[HumanMessage(content="world")]])
|
23 |
+
"""
|
24 |
+
|
25 |
+
model_name: str = "Qwen/Qwen2.5-1.5B-Instruct"
|
26 |
+
"""The name of the model"""
|
27 |
+
# other params
|
28 |
+
temperature: float = 0.7
|
29 |
+
max_new_tokens: int = 512
|
30 |
+
device_map: str = "auto"
|
31 |
+
|
32 |
+
# private attributes
|
33 |
+
_model: Any = PrivateAttr()
|
34 |
+
_tokenizer: Any = PrivateAttr()
|
35 |
+
"""The model to call"""
|
36 |
+
|
37 |
+
def __init__(self, **kwargs):
|
38 |
+
super().__init__(**kwargs)
|
39 |
+
|
40 |
+
# load qwen
|
41 |
+
self._tokenizer = AutoTokenizer.from_pretrained(
|
42 |
+
self.model_name, trust_remote_code=True
|
43 |
+
)
|
44 |
+
|
45 |
+
self._model = AutoModelForCausalLM.from_pretrained(
|
46 |
+
self.model_name,
|
47 |
+
device_map=self.device_map,
|
48 |
+
torch_dtype=torch.bfloat16,
|
49 |
+
offload_folder=None,
|
50 |
+
low_cpu_mem_usage=True,
|
51 |
+
trust_remote_code=True,
|
52 |
+
).eval()
|
53 |
+
|
54 |
+
# Adicione isto após carregar o modelo
|
55 |
+
print(f"GPU memory used: {torch.cuda.memory_allocated()/1024**3:.2f} GB")
|
56 |
+
print(f"GPU memory reserved: {torch.cuda.memory_reserved()/1024**3:.2f} GB")
|
57 |
+
|
58 |
+
def _convert_message_to_dict(self, message: BaseMessage) -> dict:
|
59 |
+
"""Messages from LangChain to format expected by QWEN"""
|
60 |
+
if isinstance(message, HumanMessage):
|
61 |
+
return {"role": "user", "content": message.content}
|
62 |
+
elif isinstance(message, AIMessage):
|
63 |
+
return {"role": "assistant", "content": message.content}
|
64 |
+
elif isinstance(message, SystemMessage):
|
65 |
+
return {"role": "system", "content": message.content}
|
66 |
+
else:
|
67 |
+
raise ValueError(f"Message type not supported: {type(message)}")
|
68 |
+
|
69 |
+
def qwen(self, messages):
|
70 |
+
# make the prompt in a way to the model understand
|
71 |
+
text = self._tokenizer.apply_chat_template(
|
72 |
+
messages, tokenize=False, add_generation_prompt=True
|
73 |
+
)
|
74 |
+
model_inputs = self._tokenizer([text], return_tensors="pt").to(
|
75 |
+
self._model.device
|
76 |
+
)
|
77 |
+
|
78 |
+
# generate the qwen text
|
79 |
+
with torch.no_grad():
|
80 |
+
generated_ids = self._model.generate(
|
81 |
+
**model_inputs,
|
82 |
+
max_new_tokens=self.max_new_tokens,
|
83 |
+
temperature=self.temperature,
|
84 |
+
)
|
85 |
+
generated_ids = [
|
86 |
+
output_ids[len(input_ids) :]
|
87 |
+
for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
|
88 |
+
]
|
89 |
+
|
90 |
+
# get the response of the LLM
|
91 |
+
response = self._tokenizer.batch_decode(
|
92 |
+
generated_ids, skip_special_tokens=True
|
93 |
+
)[0]
|
94 |
+
|
95 |
+
return response
|
96 |
+
|
97 |
+
def _generate(
|
98 |
+
self,
|
99 |
+
messages: List[BaseMessage],
|
100 |
+
stop: Optional[List[str]] = None,
|
101 |
+
run_manager: Optional[Any] = None,
|
102 |
+
**kwargs: Any,
|
103 |
+
) -> ChatResult:
|
104 |
+
"""
|
105 |
+
Args:
|
106 |
+
messages: the prompt composed of a list of messages.
|
107 |
+
"""
|
108 |
+
# parse the messages to feed qwen
|
109 |
+
formatted_messages = [self._convert_message_to_dict(msg) for msg in messages]
|
110 |
+
|
111 |
+
# call qwen
|
112 |
+
qwen_response = self.qwen(formatted_messages)
|
113 |
+
|
114 |
+
# process the stop tokens
|
115 |
+
if stop:
|
116 |
+
for stop_word in stop:
|
117 |
+
qwen_response = qwen_response.split(stop_word)[0]
|
118 |
+
|
119 |
+
# message type update
|
120 |
+
message = AIMessage(content=qwen_response.strip())
|
121 |
+
|
122 |
+
# return
|
123 |
+
generation = ChatGeneration(message=message, text=qwen_response.strip())
|
124 |
+
return ChatResult(generations=[generation])
|
125 |
+
|
126 |
+
@property
|
127 |
+
def _llm_type(self) -> str:
|
128 |
+
"""Get the type of language model used by this chat model."""
|
129 |
+
return "qwen-chat-model"
|
130 |
+
|
131 |
+
@property
|
132 |
+
def _identifying_params(self) -> Dict[str, Any]:
|
133 |
+
"""Return a dictionary of identifying parameters.
|
134 |
+
|
135 |
+
This information is used by the LangChain callback system, which
|
136 |
+
is used for tracing purposes make it possible to monitor LLMs.
|
137 |
+
"""
|
138 |
+
return {
|
139 |
+
# The model name allows users to specify custom token counting
|
140 |
+
# rules in LLM monitoring applications (e.g., in LangSmith users
|
141 |
+
# can provide per token pricing for their model and monitor
|
142 |
+
# costs for the given LLM.)
|
143 |
+
"model_name": self.model_name,
|
144 |
+
}
|
README.md
ADDED
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Book Reader
|
2 |
+
|
3 |
+
## Install
|
4 |
+
|
5 |
+
Run the bash script to install the conda environments:
|
6 |
+
|
7 |
+
```sh
|
8 |
+
bash install.sh
|
9 |
+
```
|
10 |
+
|
11 |
+
## Run
|
12 |
+
|
13 |
+
1. Run the bash script to download the models and run the APIs.
|
14 |
+
|
15 |
+
```sh
|
16 |
+
bash run.sh
|
17 |
+
```
|
18 |
+
|
19 |
+
## Example
|
install.sh
ADDED
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
# Path to the conda executable
|
4 |
+
CONDA_PATH=$(which conda)
|
5 |
+
|
6 |
+
# Check if conda is installed
|
7 |
+
if [ -z "$CONDA_PATH" ]; then
|
8 |
+
echo "Conda could not be found. Please install conda first."
|
9 |
+
exit
|
10 |
+
fi
|
11 |
+
|
12 |
+
# Initialize conda
|
13 |
+
eval "$($CONDA_PATH shell.bash hook)"
|
14 |
+
|
15 |
+
# List of conda environments to activate
|
16 |
+
ENVIRONMENTS=("specialist:3.11")
|
17 |
+
|
18 |
+
# Loop through each environment and activate it
|
19 |
+
for ENV_NAME_VERSION in "${ENVIRONMENTS[@]}"; do
|
20 |
+
# get environment name and python version
|
21 |
+
IFS=':' read -r ENV_NAME PYTHON_VERSION <<< "$ENV_NAME_VERSION"
|
22 |
+
|
23 |
+
if { conda env list | grep $ENV_NAME; } >/dev/null 2>&1; then
|
24 |
+
echo "$ENV_NAME already exists."
|
25 |
+
else
|
26 |
+
# Create the conda environment
|
27 |
+
echo "Creating conda environment: $ENV_NAME with Python version: $PYTHON_VERSION"
|
28 |
+
conda create -n $ENV_NAME python=$PYTHON_VERSION -y
|
29 |
+
fi
|
30 |
+
# Activate the conda environment
|
31 |
+
echo "Activating conda environment..."
|
32 |
+
conda activate $ENV_NAME
|
33 |
+
|
34 |
+
# Install the requirements from requirements.txt
|
35 |
+
if [ -f requirements.txt ]; then
|
36 |
+
echo "Installing requirements from requirements.txt..."
|
37 |
+
pip install -r requirements.txt
|
38 |
+
else
|
39 |
+
echo "requirements.txt file not found. Please provide the file."
|
40 |
+
exit
|
41 |
+
fi
|
42 |
+
|
43 |
+
echo "Conda environment '$ENV_NAME' is ready."
|
44 |
+
|
45 |
+
echo "Deactivating conda environment..."
|
46 |
+
conda deactivate
|
47 |
+
cd ..
|
48 |
+
done
|
49 |
+
|
50 |
+
echo "Installation complete."
|
query.py
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# chat
|
2 |
+
from QWEN import ChatQWEN
|
3 |
+
from langchain_core.prompts import ChatPromptTemplate
|
4 |
+
|
5 |
+
# prompt chat
|
6 |
+
prompt = ChatPromptTemplate(
|
7 |
+
[
|
8 |
+
(
|
9 |
+
"system",
|
10 |
+
"You are Qwen, created by Alibaba Cloud. You are a helpful assistant that translates {input_language} to {output_language}.",
|
11 |
+
),
|
12 |
+
("human", "{input}"),
|
13 |
+
]
|
14 |
+
)
|
15 |
+
|
16 |
+
# model creation
|
17 |
+
llm = ChatQWEN()
|
18 |
+
|
19 |
+
# pipeline
|
20 |
+
chain = prompt | llm
|
21 |
+
|
22 |
+
# query
|
23 |
+
print(
|
24 |
+
chain.invoke(
|
25 |
+
{
|
26 |
+
"input_language": "English",
|
27 |
+
"output_language": "German",
|
28 |
+
"input": "I love programming",
|
29 |
+
}
|
30 |
+
).content
|
31 |
+
)
|
requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
langchain-deepseek==0.1.2
|
2 |
+
torch==2.4.1
|
3 |
+
triton==3.0.0
|
4 |
+
transformers==4.46.3
|
5 |
+
safetensors==0.4.5
|
6 |
+
accelerate>=0.26.0
|
run.sh
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
# Path to the conda executable
|
4 |
+
CONDA_PATH=$(which conda)
|
5 |
+
|
6 |
+
# Check if conda is installed
|
7 |
+
if [ -z "$CONDA_PATH" ]; then
|
8 |
+
echo "Conda could not be found. Please install conda first."
|
9 |
+
exit
|
10 |
+
fi
|
11 |
+
|
12 |
+
# Initialize conda
|
13 |
+
eval "$($CONDA_PATH shell.bash hook)"
|
14 |
+
|
15 |
+
conda activate specialist
|
16 |
+
python query.py
|
17 |
+
conda deactivate
|
18 |
+
echo "Completed."
|