Upload 21 files
Browse files- .gitattributes +3 -0
- README.md +152 -3
- cnclip/cn_vocab.txt +0 -0
- cnclip/cnclip_vit_l14_336px_text_u16.axmodel +3 -0
- cnclip/cnclip_vit_l14_336px_vision_u16u8.axmodel +3 -0
- coco_1000.tar +3 -0
- config.json +137 -0
- gradio_01.png +3 -0
- install/examples/cmdline.hpp +732 -0
- install/examples/test_ax_api.cpp +37 -0
- install/examples/test_axcl_api.cpp +32 -0
- install/examples/test_enum_devices.cpp +59 -0
- install/examples/test_load_model.cpp +84 -0
- install/examples/test_match_by_text.cpp +131 -0
- install/examples/timer.hpp +61 -0
- install/include/clip.h +203 -0
- install/lib/aarch64/libclip.so +3 -0
- pyclip/example.py +51 -0
- pyclip/gradio_example.png +3 -0
- pyclip/gradio_example.py +80 -0
- pyclip/pyclip.py +260 -0
- pyclip/requirements.txt +4 -0
.gitattributes
CHANGED
|
@@ -35,3 +35,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
*.axmodel filter=lfs diff=lfs merge=lfs -text
|
| 37 |
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
*.axmodel filter=lfs diff=lfs merge=lfs -text
|
| 37 |
|
| 38 |
+
gradio_01.png filter=lfs diff=lfs merge=lfs -text
|
| 39 |
+
install/lib/aarch64/libclip.so filter=lfs diff=lfs merge=lfs -text
|
| 40 |
+
pyclip/gradio_example.png filter=lfs diff=lfs merge=lfs -text
|
README.md
CHANGED
|
@@ -1,3 +1,152 @@
|
|
| 1 |
-
---
|
| 2 |
-
license: mit
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: mit
|
| 3 |
+
language:
|
| 4 |
+
- en
|
| 5 |
+
- zh
|
| 6 |
+
base_model:
|
| 7 |
+
- OFA-Sys/chinese-clip-vit-large-patch14-336px
|
| 8 |
+
- AXERA-TECH/cnclip
|
| 9 |
+
tags:
|
| 10 |
+
- CLIP
|
| 11 |
+
- CN_CLIP
|
| 12 |
+
---
|
| 13 |
+
|
| 14 |
+
# LibCLIP
|
| 15 |
+
|
| 16 |
+
This SDK enables efficient text-to-image retrieval using CLIP (Contrastive Language–Image Pretraining), optimized for Axera’s NPU-based SoC platforms including AX650, AX650C, AX8850, and AX650A, or Axera's dedicated AI accelerator.
|
| 17 |
+
|
| 18 |
+
With this SDK, you can:
|
| 19 |
+
|
| 20 |
+
- Perform semantic image search by providing natural language queries.
|
| 21 |
+
- Utilize CLIP to embed text queries and compare them against a pre-computed set of image embeddings.
|
| 22 |
+
- Run all inference processes directly on Axera NPUs for low-latency, high-throughput performance at the edge.
|
| 23 |
+
|
| 24 |
+
This solution is well-suited for smart cameras, content filtering, AI-powered user interfaces, and other edge AI scenarios where natural language-based image retrieval is required.
|
| 25 |
+
|
| 26 |
+
## References links:
|
| 27 |
+
|
| 28 |
+
For those who are interested in model conversion, you can try to export axmodel through
|
| 29 |
+
|
| 30 |
+
- [The github repo of libclip's open source](https://github.com/AXERA-TECH/libclip.axera)
|
| 31 |
+
|
| 32 |
+
- [Pulsar2 Link, How to Convert ONNX to axmodel](https://pulsar2-docs.readthedocs.io/en/latest/pulsar2/introduction.html)
|
| 33 |
+
|
| 34 |
+
- https://huggingface.co/AXERA-TECH/cnclip
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
## Support Platform
|
| 38 |
+
|
| 39 |
+
- AX650
|
| 40 |
+
- [M4N-Dock(爱芯派Pro)](https://wiki.sipeed.com/hardware/zh/maixIV/m4ndock/m4ndock.html)
|
| 41 |
+
- [M.2 Accelerator card](https://axcl-docs.readthedocs.io/zh-cn/latest/doc_guide_hardware.html)
|
| 42 |
+
|
| 43 |
+
## Performance
|
| 44 |
+
|
| 45 |
+
| Model | Input Shape | Latency (ms) | CMM Usage (MB) |
|
| 46 |
+
| ----------------------------------------- | ----------------- | ------------ | -------------- |
|
| 47 |
+
| cnclip_vit_l14_336px_vision_u16u8.axmodel | 1 x 3 x 336 x 336 | 88.475 ms | 304 MB |
|
| 48 |
+
| cnclip_vit_l14_336px_text_u16.axmodel | 1 x 52 | 4.576 ms | 122 MB |
|
| 49 |
+
|
| 50 |
+
## How to use
|
| 51 |
+
|
| 52 |
+
Download all files from this repository to the device
|
| 53 |
+
|
| 54 |
+
```
|
| 55 |
+
(base) axera@raspberrypi:~/samples/AXERA-TECH/libclip.axera $ tree -L 2
|
| 56 |
+
.
|
| 57 |
+
├── cnclip
|
| 58 |
+
│ ├── cnclip_vit_l14_336px_text_u16.axmodel
|
| 59 |
+
│ ├── cnclip_vit_l14_336px_vision_u16u8.axmodel
|
| 60 |
+
│ └── cn_vocab.txt
|
| 61 |
+
├── coco_1000.tar
|
| 62 |
+
├── config.json
|
| 63 |
+
├── gradio_01.png
|
| 64 |
+
├── install
|
| 65 |
+
│ ├── examples
|
| 66 |
+
│ ├── include
|
| 67 |
+
│ └── lib
|
| 68 |
+
├── pyclip
|
| 69 |
+
│ ├── example.py
|
| 70 |
+
│ ├── gradio_example.png
|
| 71 |
+
│ ├── gradio_example.py
|
| 72 |
+
│ ├── libclip.so
|
| 73 |
+
│ ├── __pycache__
|
| 74 |
+
│ ├── pyclip.py
|
| 75 |
+
│ └── requirements.txt
|
| 76 |
+
└── README.md
|
| 77 |
+
|
| 78 |
+
8 directories, 13 files
|
| 79 |
+
```
|
| 80 |
+
|
| 81 |
+
### python env requirement
|
| 82 |
+
|
| 83 |
+
#### pyaxengine
|
| 84 |
+
|
| 85 |
+
https://github.com/AXERA-TECH/pyaxengine
|
| 86 |
+
|
| 87 |
+
```
|
| 88 |
+
wget https://github.com/AXERA-TECH/pyaxengine/releases/download/0.1.3.rc1/axengine-0.1.3-py3-none-any.whl
|
| 89 |
+
pip install axengine-0.1.3-py3-none-any.whl
|
| 90 |
+
```
|
| 91 |
+
|
| 92 |
+
#### others
|
| 93 |
+
|
| 94 |
+
```
|
| 95 |
+
pip install -r pyclip/requirements.txt
|
| 96 |
+
```
|
| 97 |
+
|
| 98 |
+
#### Inference with AX650 Host, such as M4N-Dock(爱芯派Pro)
|
| 99 |
+
|
| 100 |
+
TODO
|
| 101 |
+
|
| 102 |
+
#### Inference with M.2 Accelerator card
|
| 103 |
+
[What is M.2 Accelerator card?](https://axcl-docs.readthedocs.io/zh-cn/latest/doc_guide_hardware.html), Show this DEMO based on Raspberry PI 5.
|
| 104 |
+
|
| 105 |
+
```
|
| 106 |
+
(py312) axera@raspberrypi:~/samples/AXERA-TECH/libclip.axera $ export LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libstdc++.so.6
|
| 107 |
+
(py312) axera@raspberrypi:~/samples/AXERA-TECH/libclip.axera $ cp install/lib/aarch64/libclip.so pyclip/
|
| 108 |
+
(py312) axera@raspberrypi:~/samples/AXERA-TECH/libclip.axera $ tar xf coco_1000.tar
|
| 109 |
+
(py312) axera@raspberrypi:~/samples/AXERA-TECH/libclip.axera $ python pyclip/gradio_example.py --ienc cnclip/cnclip_vit_l14_336px_vision_u16u8.axmodel --tenc cnclip/cnclip_vit_l14_336px_text_u16.axmodel --vocab cnclip/cn_vocab.txt --isCN 1 --db_path clip_feat_db_coco --image_folder coco_1000/
|
| 110 |
+
Trying to load: /home/axera/samples/AXERA-TECH/libclip.axera/pyclip/aarch64/libclip.so
|
| 111 |
+
|
| 112 |
+
❌ Failed to load: /home/axera/samples/AXERA-TECH/libclip.axera/pyclip/aarch64/libclip.so
|
| 113 |
+
/home/axera/samples/AXERA-TECH/libclip.axera/pyclip/aarch64/libclip.so: cannot open shared object file: No such file or directory
|
| 114 |
+
🔍 File not found. Please verify that libclip.so exists and the path is correct.
|
| 115 |
+
|
| 116 |
+
Trying to load: /home/axera/samples/AXERA-TECH/libclip.axera/pyclip/libclip.so
|
| 117 |
+
open libax_sys.so failed
|
| 118 |
+
open libax_engine.so failed
|
| 119 |
+
✅ Successfully loaded: /home/axera/samples/AXERA-TECH/libclip.axera/pyclip/libclip.so
|
| 120 |
+
可用设备: {'host': {'available': True, 'version': '', 'mem_info': {'remain': 0, 'total': 0}}, 'devices': {'host_version': 'V3.6.2_20250603154858', 'dev_version': 'V3.6.2_20250603154858', 'count': 1, 'devices_info': [{'temp': 37, 'cpu_usage': 1, 'npu_usage': 0, 'mem_info': {'remain': 7022, 'total': 7040}}]}}
|
| 121 |
+
[I][ run][ 31]: AXCLWorker start with devid 0
|
| 122 |
+
|
| 123 |
+
input size: 1
|
| 124 |
+
name: image [unknown] [unknown]
|
| 125 |
+
1 x 3 x 336 x 336
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
output size: 1
|
| 129 |
+
name: unnorm_image_features
|
| 130 |
+
1 x 768
|
| 131 |
+
|
| 132 |
+
[I][ load_image_encoder][ 50]: nchw 336 336
|
| 133 |
+
[I][ load_image_encoder][ 60]: image feature len 768
|
| 134 |
+
|
| 135 |
+
input size: 1
|
| 136 |
+
name: text [unknown] [unknown]
|
| 137 |
+
1 x 52
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
output size: 1
|
| 141 |
+
name: unnorm_text_features
|
| 142 |
+
1 x 768
|
| 143 |
+
|
| 144 |
+
[I][ load_text_encoder][ 44]: text feature len 768
|
| 145 |
+
[I][ load_tokenizer][ 60]: text token len 52
|
| 146 |
+
100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1000/1000 [01:40<00:00, 9.93it/s]
|
| 147 |
+
* Running on local URL: http://0.0.0.0:7860
|
| 148 |
+
```
|
| 149 |
+
|
| 150 |
+
If your Raspberry PI 5 ip is 192.168.1.100, so using this URL `http://192.168.1.100:7860` with your WebApp.
|
| 151 |
+
|
| 152 |
+

|
cnclip/cn_vocab.txt
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
cnclip/cnclip_vit_l14_336px_text_u16.axmodel
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6f33786ab988ca22dbc883c9fa6ebfa842a425445e4dac945c30069a6d9d5cf8
|
| 3 |
+
size 127341129
|
cnclip/cnclip_vit_l14_336px_vision_u16u8.axmodel
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:6278e99001c198082b59219b163f7136d3049bca223be9176678ac6031348cde
|
| 3 |
+
size 334708454
|
coco_1000.tar
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:f3e18a198658270e19ced079de7a404e3478e69c2ef94fb47c87ddf056e6a541
|
| 3 |
+
size 163112960
|
config.json
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"_commit_hash": null,
|
| 3 |
+
"architectures": [
|
| 4 |
+
"InternVLChatModel"
|
| 5 |
+
],
|
| 6 |
+
"auto_map": {
|
| 7 |
+
"AutoConfig": "configuration_internvl_chat.InternVLChatConfig",
|
| 8 |
+
"AutoModel": "modeling_internvl_chat.InternVLChatModel",
|
| 9 |
+
"AutoModelForCausalLM": "modeling_internvl_chat.InternVLChatModel"
|
| 10 |
+
},
|
| 11 |
+
"downsample_ratio": 0.5,
|
| 12 |
+
"dynamic_image_size": true,
|
| 13 |
+
"force_image_size": 448,
|
| 14 |
+
"llm_config": {
|
| 15 |
+
"_name_or_path": "Qwen/Qwen2.5-0.5B-Instruct",
|
| 16 |
+
"add_cross_attention": false,
|
| 17 |
+
"architectures": [
|
| 18 |
+
"Qwen2ForCausalLM"
|
| 19 |
+
],
|
| 20 |
+
"_attn_implementation": "flash_attention_2",
|
| 21 |
+
"attention_dropout": 0.0,
|
| 22 |
+
"bad_words_ids": null,
|
| 23 |
+
"begin_suppress_tokens": null,
|
| 24 |
+
"bos_token_id": 151643,
|
| 25 |
+
"chunk_size_feed_forward": 0,
|
| 26 |
+
"cross_attention_hidden_size": null,
|
| 27 |
+
"decoder_start_token_id": null,
|
| 28 |
+
"diversity_penalty": 0.0,
|
| 29 |
+
"do_sample": false,
|
| 30 |
+
"early_stopping": false,
|
| 31 |
+
"encoder_no_repeat_ngram_size": 0,
|
| 32 |
+
"eos_token_id": 151645,
|
| 33 |
+
"exponential_decay_length_penalty": null,
|
| 34 |
+
"finetuning_task": null,
|
| 35 |
+
"forced_bos_token_id": null,
|
| 36 |
+
"forced_eos_token_id": null,
|
| 37 |
+
"hidden_act": "silu",
|
| 38 |
+
"hidden_size": 896,
|
| 39 |
+
"id2label": {
|
| 40 |
+
"0": "LABEL_0",
|
| 41 |
+
"1": "LABEL_1"
|
| 42 |
+
},
|
| 43 |
+
"initializer_range": 0.02,
|
| 44 |
+
"intermediate_size": 4864,
|
| 45 |
+
"is_decoder": false,
|
| 46 |
+
"is_encoder_decoder": false,
|
| 47 |
+
"label2id": {
|
| 48 |
+
"LABEL_0": 0,
|
| 49 |
+
"LABEL_1": 1
|
| 50 |
+
},
|
| 51 |
+
"length_penalty": 1.0,
|
| 52 |
+
"max_length": 20,
|
| 53 |
+
"max_position_embeddings": 32768,
|
| 54 |
+
"max_window_layers": 21,
|
| 55 |
+
"min_length": 0,
|
| 56 |
+
"model_type": "qwen2",
|
| 57 |
+
"no_repeat_ngram_size": 0,
|
| 58 |
+
"num_attention_heads": 14,
|
| 59 |
+
"num_beam_groups": 1,
|
| 60 |
+
"num_beams": 1,
|
| 61 |
+
"num_hidden_layers": 24,
|
| 62 |
+
"num_key_value_heads": 2,
|
| 63 |
+
"num_return_sequences": 1,
|
| 64 |
+
"output_attentions": false,
|
| 65 |
+
"output_hidden_states": false,
|
| 66 |
+
"output_scores": false,
|
| 67 |
+
"pad_token_id": null,
|
| 68 |
+
"prefix": null,
|
| 69 |
+
"problem_type": null,
|
| 70 |
+
"pruned_heads": {},
|
| 71 |
+
"remove_invalid_values": false,
|
| 72 |
+
"repetition_penalty": 1.0,
|
| 73 |
+
"return_dict": true,
|
| 74 |
+
"return_dict_in_generate": false,
|
| 75 |
+
"rms_norm_eps": 1e-06,
|
| 76 |
+
"rope_theta": 1000000.0,
|
| 77 |
+
"sep_token_id": null,
|
| 78 |
+
"sliding_window": 32768,
|
| 79 |
+
"suppress_tokens": null,
|
| 80 |
+
"task_specific_params": null,
|
| 81 |
+
"temperature": 1.0,
|
| 82 |
+
"tf_legacy_loss": false,
|
| 83 |
+
"tie_encoder_decoder": false,
|
| 84 |
+
"tie_word_embeddings": false,
|
| 85 |
+
"tokenizer_class": null,
|
| 86 |
+
"top_k": 50,
|
| 87 |
+
"top_p": 1.0,
|
| 88 |
+
"torch_dtype": "bfloat16",
|
| 89 |
+
"torchscript": false,
|
| 90 |
+
"transformers_version": "4.37.2",
|
| 91 |
+
"typical_p": 1.0,
|
| 92 |
+
"use_bfloat16": true,
|
| 93 |
+
"use_cache": true,
|
| 94 |
+
"use_sliding_window": false,
|
| 95 |
+
"vocab_size": 151674
|
| 96 |
+
},
|
| 97 |
+
"max_dynamic_patch": 12,
|
| 98 |
+
"min_dynamic_patch": 1,
|
| 99 |
+
"model_type": "internvl_chat",
|
| 100 |
+
"ps_version": "v2",
|
| 101 |
+
"select_layer": -1,
|
| 102 |
+
"template": "internvl2_5",
|
| 103 |
+
"torch_dtype": "bfloat16",
|
| 104 |
+
"use_backbone_lora": 0,
|
| 105 |
+
"use_llm_lora": 0,
|
| 106 |
+
"use_thumbnail": true,
|
| 107 |
+
"vision_config": {
|
| 108 |
+
"architectures": [
|
| 109 |
+
"InternVisionModel"
|
| 110 |
+
],
|
| 111 |
+
"attention_dropout": 0.0,
|
| 112 |
+
"drop_path_rate": 0.0,
|
| 113 |
+
"dropout": 0.0,
|
| 114 |
+
"hidden_act": "gelu",
|
| 115 |
+
"hidden_size": 1024,
|
| 116 |
+
"image_size": 448,
|
| 117 |
+
"initializer_factor": 1.0,
|
| 118 |
+
"initializer_range": 0.02,
|
| 119 |
+
"intermediate_size": 4096,
|
| 120 |
+
"layer_norm_eps": 1e-06,
|
| 121 |
+
"model_type": "intern_vit_6b",
|
| 122 |
+
"norm_type": "layer_norm",
|
| 123 |
+
"num_attention_heads": 16,
|
| 124 |
+
"num_channels": 3,
|
| 125 |
+
"num_hidden_layers": 24,
|
| 126 |
+
"output_attentions": false,
|
| 127 |
+
"output_hidden_states": false,
|
| 128 |
+
"patch_size": 14,
|
| 129 |
+
"qk_normalization": false,
|
| 130 |
+
"qkv_bias": true,
|
| 131 |
+
"return_dict": true,
|
| 132 |
+
"torch_dtype": "bfloat16",
|
| 133 |
+
"transformers_version": "4.37.2",
|
| 134 |
+
"use_bfloat16": true,
|
| 135 |
+
"use_flash_attn": true
|
| 136 |
+
}
|
| 137 |
+
}
|
gradio_01.png
ADDED
|
Git LFS Details
|
install/examples/cmdline.hpp
ADDED
|
@@ -0,0 +1,732 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*
|
| 2 |
+
Copyright (c) 2009, Hideyuki Tanaka
|
| 3 |
+
All rights reserved.
|
| 4 |
+
|
| 5 |
+
Redistribution and use in source and binary forms, with or without
|
| 6 |
+
modification, are permitted provided that the following conditions are met:
|
| 7 |
+
* Redistributions of source code must retain the above copyright
|
| 8 |
+
notice, this list of conditions and the following disclaimer.
|
| 9 |
+
* Redistributions in binary form must reproduce the above copyright
|
| 10 |
+
notice, this list of conditions and the following disclaimer in the
|
| 11 |
+
documentation and/or other materials provided with the distribution.
|
| 12 |
+
* Neither the name of the <organization> nor the
|
| 13 |
+
names of its contributors may be used to endorse or promote products
|
| 14 |
+
derived from this software without specific prior written permission.
|
| 15 |
+
|
| 16 |
+
THIS SOFTWARE IS PROVIDED BY <copyright holder> ''AS IS'' AND ANY
|
| 17 |
+
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
| 18 |
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
| 19 |
+
DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
|
| 20 |
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
| 21 |
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
| 22 |
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
| 23 |
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| 24 |
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
| 25 |
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| 26 |
+
*/
|
| 27 |
+
|
| 28 |
+
#pragma once
|
| 29 |
+
|
| 30 |
+
#include <cxxabi.h>
|
| 31 |
+
|
| 32 |
+
#include <algorithm>
|
| 33 |
+
#include <cstdlib>
|
| 34 |
+
#include <cstring>
|
| 35 |
+
#include <iostream>
|
| 36 |
+
#include <map>
|
| 37 |
+
#include <sstream>
|
| 38 |
+
#include <stdexcept>
|
| 39 |
+
#include <string>
|
| 40 |
+
#include <typeinfo>
|
| 41 |
+
#include <vector>
|
| 42 |
+
|
| 43 |
+
namespace cmdline {
|
| 44 |
+
|
| 45 |
+
namespace detail {
|
| 46 |
+
|
| 47 |
+
template <typename Target, typename Source, bool Same>
|
| 48 |
+
class lexical_cast_t {
|
| 49 |
+
public:
|
| 50 |
+
static Target cast(const Source &arg) {
|
| 51 |
+
Target ret;
|
| 52 |
+
std::stringstream ss;
|
| 53 |
+
if (!(ss << arg && ss >> ret && ss.eof())) throw std::bad_cast();
|
| 54 |
+
|
| 55 |
+
return ret;
|
| 56 |
+
}
|
| 57 |
+
};
|
| 58 |
+
|
| 59 |
+
template <typename Target, typename Source>
|
| 60 |
+
class lexical_cast_t<Target, Source, true> {
|
| 61 |
+
public:
|
| 62 |
+
static Target cast(const Source &arg) { return arg; }
|
| 63 |
+
};
|
| 64 |
+
|
| 65 |
+
template <typename Source>
|
| 66 |
+
class lexical_cast_t<std::string, Source, false> {
|
| 67 |
+
public:
|
| 68 |
+
static std::string cast(const Source &arg) {
|
| 69 |
+
std::ostringstream ss;
|
| 70 |
+
ss << arg;
|
| 71 |
+
return ss.str();
|
| 72 |
+
}
|
| 73 |
+
};
|
| 74 |
+
|
| 75 |
+
template <typename Target>
|
| 76 |
+
class lexical_cast_t<Target, std::string, false> {
|
| 77 |
+
public:
|
| 78 |
+
static Target cast(const std::string &arg) {
|
| 79 |
+
Target ret;
|
| 80 |
+
std::istringstream ss(arg);
|
| 81 |
+
if (!(ss >> ret && ss.eof())) throw std::bad_cast();
|
| 82 |
+
return ret;
|
| 83 |
+
}
|
| 84 |
+
};
|
| 85 |
+
|
| 86 |
+
template <typename T1, typename T2>
|
| 87 |
+
struct is_same {
|
| 88 |
+
static const bool value = false;
|
| 89 |
+
};
|
| 90 |
+
|
| 91 |
+
template <typename T>
|
| 92 |
+
struct is_same<T, T> {
|
| 93 |
+
static const bool value = true;
|
| 94 |
+
};
|
| 95 |
+
|
| 96 |
+
template <typename Target, typename Source>
|
| 97 |
+
Target lexical_cast(const Source &arg) {
|
| 98 |
+
return lexical_cast_t<Target, Source,
|
| 99 |
+
detail::is_same<Target, Source>::value>::cast(arg);
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
static inline std::string demangle(const std::string &name) {
|
| 103 |
+
int status = 0;
|
| 104 |
+
char *p = abi::__cxa_demangle(name.c_str(), 0, 0, &status);
|
| 105 |
+
std::string ret(p);
|
| 106 |
+
free(p);
|
| 107 |
+
return ret;
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
template <class T>
|
| 111 |
+
std::string readable_typename() {
|
| 112 |
+
return demangle(typeid(T).name());
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
+
template <class T>
|
| 116 |
+
std::string default_value(T def) {
|
| 117 |
+
return detail::lexical_cast<std::string>(def);
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
template <>
|
| 121 |
+
inline std::string readable_typename<std::string>() {
|
| 122 |
+
return "string";
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
} // namespace detail
|
| 126 |
+
|
| 127 |
+
//-----
|
| 128 |
+
|
| 129 |
+
class cmdline_error : public std::exception {
|
| 130 |
+
public:
|
| 131 |
+
cmdline_error(const std::string &msg) : msg(msg) {}
|
| 132 |
+
~cmdline_error() throw() {}
|
| 133 |
+
const char *what() const throw() { return msg.c_str(); }
|
| 134 |
+
|
| 135 |
+
private:
|
| 136 |
+
std::string msg;
|
| 137 |
+
};
|
| 138 |
+
|
| 139 |
+
template <class T>
|
| 140 |
+
struct default_reader {
|
| 141 |
+
T operator()(const std::string &str) { return detail::lexical_cast<T>(str); }
|
| 142 |
+
};
|
| 143 |
+
|
| 144 |
+
template <class T>
|
| 145 |
+
struct range_reader {
|
| 146 |
+
range_reader(const T &low, const T &high) : low(low), high(high) {}
|
| 147 |
+
T operator()(const std::string &s) const {
|
| 148 |
+
T ret = default_reader<T>()(s);
|
| 149 |
+
if (!(ret >= low && ret <= high))
|
| 150 |
+
throw cmdline::cmdline_error("range_error");
|
| 151 |
+
return ret;
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
private:
|
| 155 |
+
T low, high;
|
| 156 |
+
};
|
| 157 |
+
|
| 158 |
+
template <class T>
|
| 159 |
+
range_reader<T> range(const T &low, const T &high) {
|
| 160 |
+
return range_reader<T>(low, high);
|
| 161 |
+
}
|
| 162 |
+
|
| 163 |
+
template <class T>
|
| 164 |
+
struct oneof_reader {
|
| 165 |
+
T operator()(const std::string &s) {
|
| 166 |
+
T ret = default_reader<T>()(s);
|
| 167 |
+
if (std::find(alt.begin(), alt.end(), ret) == alt.end())
|
| 168 |
+
throw cmdline_error("");
|
| 169 |
+
return ret;
|
| 170 |
+
}
|
| 171 |
+
void add(const T &v) { alt.push_back(v); }
|
| 172 |
+
|
| 173 |
+
private:
|
| 174 |
+
std::vector<T> alt;
|
| 175 |
+
};
|
| 176 |
+
|
| 177 |
+
template <class T>
|
| 178 |
+
oneof_reader<T> oneof(T a1) {
|
| 179 |
+
oneof_reader<T> ret;
|
| 180 |
+
ret.add(a1);
|
| 181 |
+
return ret;
|
| 182 |
+
}
|
| 183 |
+
|
| 184 |
+
template <class T>
|
| 185 |
+
oneof_reader<T> oneof(T a1, T a2) {
|
| 186 |
+
oneof_reader<T> ret;
|
| 187 |
+
ret.add(a1);
|
| 188 |
+
ret.add(a2);
|
| 189 |
+
return ret;
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
template <class T>
|
| 193 |
+
oneof_reader<T> oneof(T a1, T a2, T a3) {
|
| 194 |
+
oneof_reader<T> ret;
|
| 195 |
+
ret.add(a1);
|
| 196 |
+
ret.add(a2);
|
| 197 |
+
ret.add(a3);
|
| 198 |
+
return ret;
|
| 199 |
+
}
|
| 200 |
+
|
| 201 |
+
template <class T>
|
| 202 |
+
oneof_reader<T> oneof(T a1, T a2, T a3, T a4) {
|
| 203 |
+
oneof_reader<T> ret;
|
| 204 |
+
ret.add(a1);
|
| 205 |
+
ret.add(a2);
|
| 206 |
+
ret.add(a3);
|
| 207 |
+
ret.add(a4);
|
| 208 |
+
return ret;
|
| 209 |
+
}
|
| 210 |
+
|
| 211 |
+
template <class T>
|
| 212 |
+
oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5) {
|
| 213 |
+
oneof_reader<T> ret;
|
| 214 |
+
ret.add(a1);
|
| 215 |
+
ret.add(a2);
|
| 216 |
+
ret.add(a3);
|
| 217 |
+
ret.add(a4);
|
| 218 |
+
ret.add(a5);
|
| 219 |
+
return ret;
|
| 220 |
+
}
|
| 221 |
+
|
| 222 |
+
template <class T>
|
| 223 |
+
oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6) {
|
| 224 |
+
oneof_reader<T> ret;
|
| 225 |
+
ret.add(a1);
|
| 226 |
+
ret.add(a2);
|
| 227 |
+
ret.add(a3);
|
| 228 |
+
ret.add(a4);
|
| 229 |
+
ret.add(a5);
|
| 230 |
+
ret.add(a6);
|
| 231 |
+
return ret;
|
| 232 |
+
}
|
| 233 |
+
|
| 234 |
+
template <class T>
|
| 235 |
+
oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7) {
|
| 236 |
+
oneof_reader<T> ret;
|
| 237 |
+
ret.add(a1);
|
| 238 |
+
ret.add(a2);
|
| 239 |
+
ret.add(a3);
|
| 240 |
+
ret.add(a4);
|
| 241 |
+
ret.add(a5);
|
| 242 |
+
ret.add(a6);
|
| 243 |
+
ret.add(a7);
|
| 244 |
+
return ret;
|
| 245 |
+
}
|
| 246 |
+
|
| 247 |
+
template <class T>
|
| 248 |
+
oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8) {
|
| 249 |
+
oneof_reader<T> ret;
|
| 250 |
+
ret.add(a1);
|
| 251 |
+
ret.add(a2);
|
| 252 |
+
ret.add(a3);
|
| 253 |
+
ret.add(a4);
|
| 254 |
+
ret.add(a5);
|
| 255 |
+
ret.add(a6);
|
| 256 |
+
ret.add(a7);
|
| 257 |
+
ret.add(a8);
|
| 258 |
+
return ret;
|
| 259 |
+
}
|
| 260 |
+
|
| 261 |
+
template <class T>
|
| 262 |
+
oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9) {
|
| 263 |
+
oneof_reader<T> ret;
|
| 264 |
+
ret.add(a1);
|
| 265 |
+
ret.add(a2);
|
| 266 |
+
ret.add(a3);
|
| 267 |
+
ret.add(a4);
|
| 268 |
+
ret.add(a5);
|
| 269 |
+
ret.add(a6);
|
| 270 |
+
ret.add(a7);
|
| 271 |
+
ret.add(a8);
|
| 272 |
+
ret.add(a9);
|
| 273 |
+
return ret;
|
| 274 |
+
}
|
| 275 |
+
|
| 276 |
+
template <class T>
|
| 277 |
+
oneof_reader<T> oneof(T a1, T a2, T a3, T a4, T a5, T a6, T a7, T a8, T a9,
|
| 278 |
+
T a10) {
|
| 279 |
+
oneof_reader<T> ret;
|
| 280 |
+
ret.add(a1);
|
| 281 |
+
ret.add(a2);
|
| 282 |
+
ret.add(a3);
|
| 283 |
+
ret.add(a4);
|
| 284 |
+
ret.add(a5);
|
| 285 |
+
ret.add(a6);
|
| 286 |
+
ret.add(a7);
|
| 287 |
+
ret.add(a8);
|
| 288 |
+
ret.add(a9);
|
| 289 |
+
ret.add(a10);
|
| 290 |
+
return ret;
|
| 291 |
+
}
|
| 292 |
+
|
| 293 |
+
//-----
|
| 294 |
+
|
| 295 |
+
class parser {
|
| 296 |
+
public:
|
| 297 |
+
parser() {}
|
| 298 |
+
~parser() {
|
| 299 |
+
for (std::map<std::string, option_base *>::iterator p = options.begin();
|
| 300 |
+
p != options.end(); p++)
|
| 301 |
+
delete p->second;
|
| 302 |
+
}
|
| 303 |
+
|
| 304 |
+
void add(const std::string &name, char short_name = 0,
|
| 305 |
+
const std::string &desc = "") {
|
| 306 |
+
if (options.count(name))
|
| 307 |
+
throw cmdline_error("multiple definition: " + name);
|
| 308 |
+
options[name] = new option_without_value(name, short_name, desc);
|
| 309 |
+
ordered.push_back(options[name]);
|
| 310 |
+
}
|
| 311 |
+
|
| 312 |
+
template <class T>
|
| 313 |
+
void add(const std::string &name, char short_name = 0,
|
| 314 |
+
const std::string &desc = "", bool need = true, const T def = T()) {
|
| 315 |
+
add(name, short_name, desc, need, def, default_reader<T>());
|
| 316 |
+
}
|
| 317 |
+
|
| 318 |
+
template <class T, class F>
|
| 319 |
+
void add(const std::string &name, char short_name = 0,
|
| 320 |
+
const std::string &desc = "", bool need = true, const T def = T(),
|
| 321 |
+
F reader = F()) {
|
| 322 |
+
if (options.count(name))
|
| 323 |
+
throw cmdline_error("multiple definition: " + name);
|
| 324 |
+
options[name] = new option_with_value_with_reader<T, F>(
|
| 325 |
+
name, short_name, need, def, desc, reader);
|
| 326 |
+
ordered.push_back(options[name]);
|
| 327 |
+
}
|
| 328 |
+
|
| 329 |
+
void footer(const std::string &f) { ftr = f; }
|
| 330 |
+
|
| 331 |
+
void set_program_name(const std::string &name) { prog_name = name; }
|
| 332 |
+
|
| 333 |
+
bool exist(const std::string &name) const {
|
| 334 |
+
if (options.count(name) == 0)
|
| 335 |
+
throw cmdline_error("there is no flag: --" + name);
|
| 336 |
+
return options.find(name)->second->has_set();
|
| 337 |
+
}
|
| 338 |
+
|
| 339 |
+
template <class T>
|
| 340 |
+
const T &get(const std::string &name) const {
|
| 341 |
+
if (options.count(name) == 0)
|
| 342 |
+
throw cmdline_error("there is no flag: --" + name);
|
| 343 |
+
const option_with_value<T> *p =
|
| 344 |
+
dynamic_cast<const option_with_value<T> *>(options.find(name)->second);
|
| 345 |
+
if (p == NULL) throw cmdline_error("type mismatch flag '" + name + "'");
|
| 346 |
+
return p->get();
|
| 347 |
+
}
|
| 348 |
+
|
| 349 |
+
const std::vector<std::string> &rest() const { return others; }
|
| 350 |
+
|
| 351 |
+
bool parse(const std::string &arg) {
|
| 352 |
+
std::vector<std::string> args;
|
| 353 |
+
|
| 354 |
+
std::string buf;
|
| 355 |
+
bool in_quote = false;
|
| 356 |
+
for (std::string::size_type i = 0; i < arg.length(); i++) {
|
| 357 |
+
if (arg[i] == '\"') {
|
| 358 |
+
in_quote = !in_quote;
|
| 359 |
+
continue;
|
| 360 |
+
}
|
| 361 |
+
|
| 362 |
+
if (arg[i] == ' ' && !in_quote) {
|
| 363 |
+
args.push_back(buf);
|
| 364 |
+
buf = "";
|
| 365 |
+
continue;
|
| 366 |
+
}
|
| 367 |
+
|
| 368 |
+
if (arg[i] == '\\') {
|
| 369 |
+
i++;
|
| 370 |
+
if (i >= arg.length()) {
|
| 371 |
+
errors.push_back("unexpected occurrence of '\\' at end of string");
|
| 372 |
+
return false;
|
| 373 |
+
}
|
| 374 |
+
}
|
| 375 |
+
|
| 376 |
+
buf += arg[i];
|
| 377 |
+
}
|
| 378 |
+
|
| 379 |
+
if (in_quote) {
|
| 380 |
+
errors.push_back("quote is not closed");
|
| 381 |
+
return false;
|
| 382 |
+
}
|
| 383 |
+
|
| 384 |
+
if (buf.length() > 0) args.push_back(buf);
|
| 385 |
+
|
| 386 |
+
for (size_t i = 0; i < args.size(); i++)
|
| 387 |
+
std::cout << "\"" << args[i] << "\"" << std::endl;
|
| 388 |
+
|
| 389 |
+
return parse(args);
|
| 390 |
+
}
|
| 391 |
+
|
| 392 |
+
bool parse(const std::vector<std::string> &args) {
|
| 393 |
+
int argc = static_cast<int>(args.size());
|
| 394 |
+
std::vector<const char *> argv(argc);
|
| 395 |
+
|
| 396 |
+
for (int i = 0; i < argc; i++) argv[i] = args[i].c_str();
|
| 397 |
+
|
| 398 |
+
return parse(argc, &argv[0]);
|
| 399 |
+
}
|
| 400 |
+
|
| 401 |
+
bool parse(int argc, const char *const argv[]) {
|
| 402 |
+
errors.clear();
|
| 403 |
+
others.clear();
|
| 404 |
+
|
| 405 |
+
if (argc < 1) {
|
| 406 |
+
errors.push_back("argument number must be longer than 0");
|
| 407 |
+
return false;
|
| 408 |
+
}
|
| 409 |
+
if (prog_name == "") prog_name = argv[0];
|
| 410 |
+
|
| 411 |
+
std::map<char, std::string> lookup;
|
| 412 |
+
for (std::map<std::string, option_base *>::iterator p = options.begin();
|
| 413 |
+
p != options.end(); p++) {
|
| 414 |
+
if (p->first.length() == 0) continue;
|
| 415 |
+
char initial = p->second->short_name();
|
| 416 |
+
if (initial) {
|
| 417 |
+
if (lookup.count(initial) > 0) {
|
| 418 |
+
lookup[initial] = "";
|
| 419 |
+
errors.push_back(std::string("short option '") + initial +
|
| 420 |
+
"' is ambiguous");
|
| 421 |
+
return false;
|
| 422 |
+
} else
|
| 423 |
+
lookup[initial] = p->first;
|
| 424 |
+
}
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
+
for (int i = 1; i < argc; i++) {
|
| 428 |
+
if (strncmp(argv[i], "--", 2) == 0) {
|
| 429 |
+
const char *p = strchr(argv[i] + 2, '=');
|
| 430 |
+
if (p) {
|
| 431 |
+
std::string name(argv[i] + 2, p);
|
| 432 |
+
std::string val(p + 1);
|
| 433 |
+
set_option(name, val);
|
| 434 |
+
} else {
|
| 435 |
+
std::string name(argv[i] + 2);
|
| 436 |
+
if (options.count(name) == 0) {
|
| 437 |
+
errors.push_back("undefined option: --" + name);
|
| 438 |
+
continue;
|
| 439 |
+
}
|
| 440 |
+
if (options[name]->has_value()) {
|
| 441 |
+
if (i + 1 >= argc) {
|
| 442 |
+
errors.push_back("option needs value: --" + name);
|
| 443 |
+
continue;
|
| 444 |
+
} else {
|
| 445 |
+
i++;
|
| 446 |
+
set_option(name, argv[i]);
|
| 447 |
+
}
|
| 448 |
+
} else {
|
| 449 |
+
set_option(name);
|
| 450 |
+
}
|
| 451 |
+
}
|
| 452 |
+
} else if (strncmp(argv[i], "-", 1) == 0) {
|
| 453 |
+
if (!argv[i][1]) continue;
|
| 454 |
+
char last = argv[i][1];
|
| 455 |
+
for (int j = 2; argv[i][j]; j++) {
|
| 456 |
+
last = argv[i][j];
|
| 457 |
+
if (lookup.count(argv[i][j - 1]) == 0) {
|
| 458 |
+
errors.push_back(std::string("undefined short option: -") +
|
| 459 |
+
argv[i][j - 1]);
|
| 460 |
+
continue;
|
| 461 |
+
}
|
| 462 |
+
if (lookup[argv[i][j - 1]] == "") {
|
| 463 |
+
errors.push_back(std::string("ambiguous short option: -") +
|
| 464 |
+
argv[i][j - 1]);
|
| 465 |
+
continue;
|
| 466 |
+
}
|
| 467 |
+
set_option(lookup[argv[i][j - 1]]);
|
| 468 |
+
}
|
| 469 |
+
|
| 470 |
+
if (lookup.count(last) == 0) {
|
| 471 |
+
errors.push_back(std::string("undefined short option: -") + last);
|
| 472 |
+
continue;
|
| 473 |
+
}
|
| 474 |
+
if (lookup[last] == "") {
|
| 475 |
+
errors.push_back(std::string("ambiguous short option: -") + last);
|
| 476 |
+
continue;
|
| 477 |
+
}
|
| 478 |
+
|
| 479 |
+
if (i + 1 < argc && options[lookup[last]]->has_value()) {
|
| 480 |
+
set_option(lookup[last], argv[i + 1]);
|
| 481 |
+
i++;
|
| 482 |
+
} else {
|
| 483 |
+
set_option(lookup[last]);
|
| 484 |
+
}
|
| 485 |
+
} else {
|
| 486 |
+
others.push_back(argv[i]);
|
| 487 |
+
}
|
| 488 |
+
}
|
| 489 |
+
|
| 490 |
+
for (std::map<std::string, option_base *>::iterator p = options.begin();
|
| 491 |
+
p != options.end(); p++)
|
| 492 |
+
if (!p->second->valid())
|
| 493 |
+
errors.push_back("need option: --" + std::string(p->first));
|
| 494 |
+
|
| 495 |
+
return errors.size() == 0;
|
| 496 |
+
}
|
| 497 |
+
|
| 498 |
+
void parse_check(const std::string &arg) {
|
| 499 |
+
if (!options.count("help")) add("help", '?', "print this message");
|
| 500 |
+
check(0, parse(arg));
|
| 501 |
+
}
|
| 502 |
+
|
| 503 |
+
void parse_check(const std::vector<std::string> &args) {
|
| 504 |
+
if (!options.count("help")) add("help", '?', "print this message");
|
| 505 |
+
check(args.size(), parse(args));
|
| 506 |
+
}
|
| 507 |
+
|
| 508 |
+
void parse_check(int argc, char *argv[]) {
|
| 509 |
+
if (!options.count("help")) add("help", '?', "print this message");
|
| 510 |
+
check(argc, parse(argc, argv));
|
| 511 |
+
}
|
| 512 |
+
|
| 513 |
+
std::string error() const { return errors.size() > 0 ? errors[0] : ""; }
|
| 514 |
+
|
| 515 |
+
std::string error_full() const {
|
| 516 |
+
std::ostringstream oss;
|
| 517 |
+
for (size_t i = 0; i < errors.size(); i++) oss << errors[i] << std::endl;
|
| 518 |
+
return oss.str();
|
| 519 |
+
}
|
| 520 |
+
|
| 521 |
+
std::string usage() const {
|
| 522 |
+
std::ostringstream oss;
|
| 523 |
+
oss << "usage: " << prog_name << " ";
|
| 524 |
+
for (size_t i = 0; i < ordered.size(); i++) {
|
| 525 |
+
if (ordered[i]->must()) oss << ordered[i]->short_description() << " ";
|
| 526 |
+
}
|
| 527 |
+
|
| 528 |
+
oss << "[options] ... " << ftr << std::endl;
|
| 529 |
+
oss << "options:" << std::endl;
|
| 530 |
+
|
| 531 |
+
size_t max_width = 0;
|
| 532 |
+
for (size_t i = 0; i < ordered.size(); i++) {
|
| 533 |
+
max_width = std::max(max_width, ordered[i]->name().length());
|
| 534 |
+
}
|
| 535 |
+
for (size_t i = 0; i < ordered.size(); i++) {
|
| 536 |
+
if (ordered[i]->short_name()) {
|
| 537 |
+
oss << " -" << ordered[i]->short_name() << ", ";
|
| 538 |
+
} else {
|
| 539 |
+
oss << " ";
|
| 540 |
+
}
|
| 541 |
+
|
| 542 |
+
oss << "--" << ordered[i]->name();
|
| 543 |
+
for (size_t j = ordered[i]->name().length(); j < max_width + 4; j++)
|
| 544 |
+
oss << ' ';
|
| 545 |
+
oss << ordered[i]->description() << std::endl;
|
| 546 |
+
}
|
| 547 |
+
return oss.str();
|
| 548 |
+
}
|
| 549 |
+
|
| 550 |
+
private:
|
| 551 |
+
void check(int argc, bool ok) {
|
| 552 |
+
if ((argc == 1 && !ok) || exist("help")) {
|
| 553 |
+
std::cerr << usage();
|
| 554 |
+
exit(0);
|
| 555 |
+
}
|
| 556 |
+
|
| 557 |
+
if (!ok) {
|
| 558 |
+
std::cerr << error() << std::endl << usage();
|
| 559 |
+
exit(1);
|
| 560 |
+
}
|
| 561 |
+
}
|
| 562 |
+
|
| 563 |
+
void set_option(const std::string &name) {
|
| 564 |
+
if (options.count(name) == 0) {
|
| 565 |
+
errors.push_back("undefined option: --" + name);
|
| 566 |
+
return;
|
| 567 |
+
}
|
| 568 |
+
if (!options[name]->set()) {
|
| 569 |
+
errors.push_back("option needs value: --" + name);
|
| 570 |
+
return;
|
| 571 |
+
}
|
| 572 |
+
}
|
| 573 |
+
|
| 574 |
+
void set_option(const std::string &name, const std::string &value) {
|
| 575 |
+
if (options.count(name) == 0) {
|
| 576 |
+
errors.push_back("undefined option: --" + name);
|
| 577 |
+
return;
|
| 578 |
+
}
|
| 579 |
+
if (!options[name]->set(value)) {
|
| 580 |
+
errors.push_back("option value is invalid: --" + name + "=" + value);
|
| 581 |
+
return;
|
| 582 |
+
}
|
| 583 |
+
}
|
| 584 |
+
|
| 585 |
+
class option_base {
|
| 586 |
+
public:
|
| 587 |
+
virtual ~option_base() {}
|
| 588 |
+
|
| 589 |
+
virtual bool has_value() const = 0;
|
| 590 |
+
virtual bool set() = 0;
|
| 591 |
+
virtual bool set(const std::string &value) = 0;
|
| 592 |
+
virtual bool has_set() const = 0;
|
| 593 |
+
virtual bool valid() const = 0;
|
| 594 |
+
virtual bool must() const = 0;
|
| 595 |
+
|
| 596 |
+
virtual const std::string &name() const = 0;
|
| 597 |
+
virtual char short_name() const = 0;
|
| 598 |
+
virtual const std::string &description() const = 0;
|
| 599 |
+
virtual std::string short_description() const = 0;
|
| 600 |
+
};
|
| 601 |
+
|
| 602 |
+
class option_without_value : public option_base {
|
| 603 |
+
public:
|
| 604 |
+
option_without_value(const std::string &name, char short_name,
|
| 605 |
+
const std::string &desc)
|
| 606 |
+
: nam(name), snam(short_name), desc(desc), has(false) {}
|
| 607 |
+
~option_without_value() {}
|
| 608 |
+
|
| 609 |
+
bool has_value() const { return false; }
|
| 610 |
+
|
| 611 |
+
bool set() {
|
| 612 |
+
has = true;
|
| 613 |
+
return true;
|
| 614 |
+
}
|
| 615 |
+
|
| 616 |
+
bool set(const std::string &) { return false; }
|
| 617 |
+
|
| 618 |
+
bool has_set() const { return has; }
|
| 619 |
+
|
| 620 |
+
bool valid() const { return true; }
|
| 621 |
+
|
| 622 |
+
bool must() const { return false; }
|
| 623 |
+
|
| 624 |
+
const std::string &name() const { return nam; }
|
| 625 |
+
|
| 626 |
+
char short_name() const { return snam; }
|
| 627 |
+
|
| 628 |
+
const std::string &description() const { return desc; }
|
| 629 |
+
|
| 630 |
+
std::string short_description() const { return "--" + nam; }
|
| 631 |
+
|
| 632 |
+
private:
|
| 633 |
+
std::string nam;
|
| 634 |
+
char snam;
|
| 635 |
+
std::string desc;
|
| 636 |
+
bool has;
|
| 637 |
+
};
|
| 638 |
+
|
| 639 |
+
template <class T>
|
| 640 |
+
class option_with_value : public option_base {
|
| 641 |
+
public:
|
| 642 |
+
option_with_value(const std::string &name, char short_name, bool need,
|
| 643 |
+
const T &def, const std::string &desc)
|
| 644 |
+
: nam(name),
|
| 645 |
+
snam(short_name),
|
| 646 |
+
need(need),
|
| 647 |
+
has(false),
|
| 648 |
+
def(def),
|
| 649 |
+
actual(def) {
|
| 650 |
+
this->desc = full_description(desc);
|
| 651 |
+
}
|
| 652 |
+
~option_with_value() {}
|
| 653 |
+
|
| 654 |
+
const T &get() const { return actual; }
|
| 655 |
+
|
| 656 |
+
bool has_value() const { return true; }
|
| 657 |
+
|
| 658 |
+
bool set() { return false; }
|
| 659 |
+
|
| 660 |
+
bool set(const std::string &value) {
|
| 661 |
+
try {
|
| 662 |
+
actual = read(value);
|
| 663 |
+
has = true;
|
| 664 |
+
} catch (const std::exception &e) {
|
| 665 |
+
return false;
|
| 666 |
+
}
|
| 667 |
+
return true;
|
| 668 |
+
}
|
| 669 |
+
|
| 670 |
+
bool has_set() const { return has; }
|
| 671 |
+
|
| 672 |
+
bool valid() const {
|
| 673 |
+
if (need && !has) return false;
|
| 674 |
+
return true;
|
| 675 |
+
}
|
| 676 |
+
|
| 677 |
+
bool must() const { return need; }
|
| 678 |
+
|
| 679 |
+
const std::string &name() const { return nam; }
|
| 680 |
+
|
| 681 |
+
char short_name() const { return snam; }
|
| 682 |
+
|
| 683 |
+
const std::string &description() const { return desc; }
|
| 684 |
+
|
| 685 |
+
std::string short_description() const {
|
| 686 |
+
return "--" + nam + "=" + detail::readable_typename<T>();
|
| 687 |
+
}
|
| 688 |
+
|
| 689 |
+
protected:
|
| 690 |
+
std::string full_description(const std::string &desc) {
|
| 691 |
+
return desc + " (" + detail::readable_typename<T>() +
|
| 692 |
+
(need ? "" : " [=" + detail::default_value<T>(def) + "]") + ")";
|
| 693 |
+
}
|
| 694 |
+
|
| 695 |
+
virtual T read(const std::string &s) = 0;
|
| 696 |
+
|
| 697 |
+
std::string nam;
|
| 698 |
+
char snam;
|
| 699 |
+
bool need;
|
| 700 |
+
std::string desc;
|
| 701 |
+
|
| 702 |
+
bool has;
|
| 703 |
+
T def;
|
| 704 |
+
T actual;
|
| 705 |
+
};
|
| 706 |
+
|
| 707 |
+
template <class T, class F>
|
| 708 |
+
class option_with_value_with_reader : public option_with_value<T> {
|
| 709 |
+
public:
|
| 710 |
+
option_with_value_with_reader(const std::string &name, char short_name,
|
| 711 |
+
bool need, const T def,
|
| 712 |
+
const std::string &desc, F reader)
|
| 713 |
+
: option_with_value<T>(name, short_name, need, def, desc),
|
| 714 |
+
reader(reader) {}
|
| 715 |
+
|
| 716 |
+
private:
|
| 717 |
+
T read(const std::string &s) { return reader(s); }
|
| 718 |
+
|
| 719 |
+
F reader;
|
| 720 |
+
};
|
| 721 |
+
|
| 722 |
+
std::map<std::string, option_base *> options;
|
| 723 |
+
std::vector<option_base *> ordered;
|
| 724 |
+
std::string ftr;
|
| 725 |
+
|
| 726 |
+
std::string prog_name;
|
| 727 |
+
std::vector<std::string> others;
|
| 728 |
+
|
| 729 |
+
std::vector<std::string> errors;
|
| 730 |
+
};
|
| 731 |
+
|
| 732 |
+
} // namespace cmdline
|
install/examples/test_ax_api.cpp
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "runner/ax650/ax_api_loader.h"
|
| 2 |
+
#include "runner/ax650/ax_model_runner_ax650.hpp"
|
| 3 |
+
|
| 4 |
+
#include <fstream>
|
| 5 |
+
#include <vector>
|
| 6 |
+
#include <cstring>
|
| 7 |
+
|
| 8 |
+
AxSysApiLoader &get_ax_sys_loader();
|
| 9 |
+
|
| 10 |
+
AxEngineApiLoader &get_ax_engine_loader();
|
| 11 |
+
|
| 12 |
+
int main()
|
| 13 |
+
{
|
| 14 |
+
AxSysApiLoader &ax_sys_loader = get_ax_sys_loader();
|
| 15 |
+
|
| 16 |
+
AxEngineApiLoader &ax_engine_loader = get_ax_engine_loader();
|
| 17 |
+
|
| 18 |
+
ax_sys_loader.AX_SYS_Init();
|
| 19 |
+
AX_ENGINE_NPU_ATTR_T npu_attr;
|
| 20 |
+
memset(&npu_attr, 0, sizeof(AX_ENGINE_NPU_ATTR_T));
|
| 21 |
+
npu_attr.eHardMode = AX_ENGINE_VIRTUAL_NPU_DISABLE;
|
| 22 |
+
ax_engine_loader.AX_ENGINE_Init(&npu_attr);
|
| 23 |
+
|
| 24 |
+
ax_runner_ax650 runner;
|
| 25 |
+
std::ifstream file("cnclip/cnclip_vit_l14_336px_text_u16.axmodel", std::ios::binary);
|
| 26 |
+
if (!file.is_open())
|
| 27 |
+
{
|
| 28 |
+
printf("open file failed\n");
|
| 29 |
+
return -1;
|
| 30 |
+
}
|
| 31 |
+
std::vector<uint8_t> model_data((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
| 32 |
+
runner.init(model_data.data(), model_data.size(), 0);
|
| 33 |
+
|
| 34 |
+
ax_engine_loader.AX_ENGINE_Deinit();
|
| 35 |
+
ax_sys_loader.AX_SYS_Deinit();
|
| 36 |
+
return 0;
|
| 37 |
+
}
|
install/examples/test_axcl_api.cpp
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "runner/axcl/axcl_manager.h"
|
| 2 |
+
#include "runner/axcl/ax_model_runner_axcl.hpp"
|
| 3 |
+
|
| 4 |
+
#include <fstream>
|
| 5 |
+
|
| 6 |
+
int main()
|
| 7 |
+
{
|
| 8 |
+
auto ret = axclInit();
|
| 9 |
+
if (ret != 0)
|
| 10 |
+
{
|
| 11 |
+
printf("axclInit failed\n");
|
| 12 |
+
return -1;
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
axcl_Dev_Init(0);
|
| 16 |
+
|
| 17 |
+
ax_runner_axcl runner;
|
| 18 |
+
std::ifstream file("cnclip/cnclip_vit_l14_336px_text_u16.axmodel", std::ios::binary);
|
| 19 |
+
if (!file.is_open())
|
| 20 |
+
{
|
| 21 |
+
printf("open file failed\n");
|
| 22 |
+
return -1;
|
| 23 |
+
}
|
| 24 |
+
std::vector<uint8_t> model_data((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
|
| 25 |
+
runner.init(model_data.data(), model_data.size(), 0);
|
| 26 |
+
|
| 27 |
+
runner.deinit();
|
| 28 |
+
|
| 29 |
+
axcl_Dev_Exit(0);
|
| 30 |
+
axclFinalize();
|
| 31 |
+
return 0;
|
| 32 |
+
}
|
install/examples/test_enum_devices.cpp
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "clip.h"
|
| 2 |
+
#include <iostream>
|
| 3 |
+
#include <cstring>
|
| 4 |
+
|
| 5 |
+
int main()
|
| 6 |
+
{
|
| 7 |
+
clip_devices_t clip_devices;
|
| 8 |
+
memset(&clip_devices, 0, sizeof(clip_devices_t));
|
| 9 |
+
if (clip_enum_devices(&clip_devices) != 0)
|
| 10 |
+
{
|
| 11 |
+
printf("enum devices failed\n");
|
| 12 |
+
return -1;
|
| 13 |
+
}
|
| 14 |
+
|
| 15 |
+
std::cout << "host npu avaiable:" << static_cast<int>(clip_devices.host.available) << " version:" << clip_devices.host.version << std::endl;
|
| 16 |
+
std::cout << "host mem total:" << clip_devices.host.mem_info.total << " MiB remain:" << clip_devices.host.mem_info.remain << " MiB" << std::endl;
|
| 17 |
+
|
| 18 |
+
std::cout << "Host Version: " << clip_devices.devices.host_version << std::endl;
|
| 19 |
+
std::cout << "Dev Version: " << clip_devices.devices.dev_version << std::endl;
|
| 20 |
+
std::cout << "Detected Devices Count: " << static_cast<int>(clip_devices.devices.count) << std::endl;
|
| 21 |
+
|
| 22 |
+
for (unsigned char i = 0; i < clip_devices.devices.count; ++i)
|
| 23 |
+
{
|
| 24 |
+
std::cout << " Device " << static_cast<int>(i) << ":" << std::endl;
|
| 25 |
+
std::cout << " Temperature: " << clip_devices.devices.devices_info[i].temp << "C" << std::endl;
|
| 26 |
+
std::cout << " CPU Usage: " << clip_devices.devices.devices_info[i].cpu_usage << "%" << std::endl;
|
| 27 |
+
std::cout << " NPU Usage: " << clip_devices.devices.devices_info[i].npu_usage << "%" << std::endl;
|
| 28 |
+
std::cout << " Memory Remaining: " << clip_devices.devices.devices_info[i].mem_info.remain << " MiB" << std::endl;
|
| 29 |
+
std::cout << " Memory Total: " << clip_devices.devices.devices_info[i].mem_info.total << " MiB" << std::endl;
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
if (clip_devices.host.available)
|
| 33 |
+
{
|
| 34 |
+
clip_sys_init(host_device, -1);
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
+
if (clip_devices.devices.count > 0)
|
| 38 |
+
{
|
| 39 |
+
for (unsigned char i = 0; i < clip_devices.devices.count; ++i)
|
| 40 |
+
{
|
| 41 |
+
clip_sys_init(axcl_device, i);
|
| 42 |
+
}
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
if (clip_devices.host.available)
|
| 46 |
+
{
|
| 47 |
+
clip_sys_deinit(host_device, -1);
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
if (clip_devices.devices.count > 0)
|
| 51 |
+
{
|
| 52 |
+
for (unsigned char i = 0; i < clip_devices.devices.count; ++i)
|
| 53 |
+
{
|
| 54 |
+
clip_sys_deinit(axcl_device, i);
|
| 55 |
+
}
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
return 0;
|
| 59 |
+
}
|
install/examples/test_load_model.cpp
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "clip.h"
|
| 2 |
+
#include "cmdline.hpp"
|
| 3 |
+
#include <fstream>
|
| 4 |
+
#include <cstring>
|
| 5 |
+
|
| 6 |
+
int main(int argc, char *argv[])
|
| 7 |
+
{
|
| 8 |
+
clip_devices_t clip_devices;
|
| 9 |
+
memset(&clip_devices, 0, sizeof(clip_devices_t));
|
| 10 |
+
if (clip_enum_devices(&clip_devices) != 0)
|
| 11 |
+
{
|
| 12 |
+
printf("enum devices failed\n");
|
| 13 |
+
return -1;
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
if (clip_devices.host.available)
|
| 17 |
+
{
|
| 18 |
+
clip_sys_init(host_device, -1);
|
| 19 |
+
}
|
| 20 |
+
else if (clip_devices.devices.count > 0)
|
| 21 |
+
{
|
| 22 |
+
clip_sys_init(axcl_device, 0);
|
| 23 |
+
}
|
| 24 |
+
else
|
| 25 |
+
{
|
| 26 |
+
printf("no device available\n");
|
| 27 |
+
return -1;
|
| 28 |
+
}
|
| 29 |
+
|
| 30 |
+
clip_init_t init_info;
|
| 31 |
+
memset(&init_info, 0, sizeof(init_info));
|
| 32 |
+
|
| 33 |
+
cmdline::parser parser;
|
| 34 |
+
parser.add<std::string>("ienc", 0, "encoder model(onnx model or axmodel)", true, "cnclip/cnclip_vit_l14_336px_vision_u16u8.axmodel");
|
| 35 |
+
parser.add<std::string>("tenc", 0, "text encoder model(onnx model or axmodel)", true, "cnclip/cnclip_vit_l14_336px_text_u16.axmodel");
|
| 36 |
+
parser.add<std::string>("vocab", 'v', "vocab path", true, "cnclip/cn_vocab.txt");
|
| 37 |
+
parser.add<int>("language", 'l', "language choose, 0:english 1:chinese", false, 1);
|
| 38 |
+
parser.add<std::string>("db_path", 'd', "db path", false, "");
|
| 39 |
+
parser.parse_check(argc, argv);
|
| 40 |
+
|
| 41 |
+
sprintf(init_info.image_encoder_path, "%s", parser.get<std::string>("ienc").c_str());
|
| 42 |
+
sprintf(init_info.text_encoder_path, "%s", parser.get<std::string>("tenc").c_str());
|
| 43 |
+
sprintf(init_info.tokenizer_path, "%s", parser.get<std::string>("vocab").c_str());
|
| 44 |
+
init_info.isCN = parser.get<int>("language");
|
| 45 |
+
sprintf(init_info.db_path, "%s", parser.get<std::string>("db_path").c_str());
|
| 46 |
+
|
| 47 |
+
printf("image_encoder_path: %s\n", init_info.image_encoder_path);
|
| 48 |
+
printf("text_encoder_path: %s\n", init_info.text_encoder_path);
|
| 49 |
+
printf("tokenizer_path: %s\n", init_info.tokenizer_path);
|
| 50 |
+
printf("isCN: %d\n", init_info.isCN);
|
| 51 |
+
printf("db_path: %s\n", init_info.db_path);
|
| 52 |
+
|
| 53 |
+
if (clip_devices.host.available)
|
| 54 |
+
{
|
| 55 |
+
init_info.dev_type = host_device;
|
| 56 |
+
}
|
| 57 |
+
else if (clip_devices.devices.count > 0)
|
| 58 |
+
{
|
| 59 |
+
init_info.dev_type = axcl_device;
|
| 60 |
+
init_info.devid = 0;
|
| 61 |
+
}
|
| 62 |
+
|
| 63 |
+
clip_handle_t handle;
|
| 64 |
+
int ret = clip_create(&init_info, &handle);
|
| 65 |
+
if (ret != clip_errcode_success)
|
| 66 |
+
{
|
| 67 |
+
printf("clip_create failed\n");
|
| 68 |
+
return -1;
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
clip_destroy(handle);
|
| 72 |
+
|
| 73 |
+
if (clip_devices.host.available)
|
| 74 |
+
{
|
| 75 |
+
clip_sys_deinit(host_device, -1);
|
| 76 |
+
}
|
| 77 |
+
else if (clip_devices.devices.count > 0)
|
| 78 |
+
{
|
| 79 |
+
|
| 80 |
+
clip_sys_deinit(axcl_device, 0);
|
| 81 |
+
}
|
| 82 |
+
|
| 83 |
+
return 0;
|
| 84 |
+
}
|
install/examples/test_match_by_text.cpp
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include "clip.h"
|
| 2 |
+
#include "cmdline.hpp"
|
| 3 |
+
#include "timer.hpp"
|
| 4 |
+
#include <fstream>
|
| 5 |
+
#include <cstring>
|
| 6 |
+
#include <opencv2/opencv.hpp>
|
| 7 |
+
|
| 8 |
+
int main(int argc, char *argv[])
|
| 9 |
+
{
|
| 10 |
+
clip_devices_t clip_devices;
|
| 11 |
+
memset(&clip_devices, 0, sizeof(clip_devices_t));
|
| 12 |
+
if (clip_enum_devices(&clip_devices) != 0)
|
| 13 |
+
{
|
| 14 |
+
printf("enum devices failed\n");
|
| 15 |
+
return -1;
|
| 16 |
+
}
|
| 17 |
+
|
| 18 |
+
if (clip_devices.host.available)
|
| 19 |
+
{
|
| 20 |
+
clip_sys_init(host_device, -1);
|
| 21 |
+
}
|
| 22 |
+
else if (clip_devices.devices.count > 0)
|
| 23 |
+
{
|
| 24 |
+
clip_sys_init(axcl_device, 0);
|
| 25 |
+
}
|
| 26 |
+
else
|
| 27 |
+
{
|
| 28 |
+
printf("no device available\n");
|
| 29 |
+
return -1;
|
| 30 |
+
}
|
| 31 |
+
|
| 32 |
+
clip_init_t init_info;
|
| 33 |
+
memset(&init_info, 0, sizeof(init_info));
|
| 34 |
+
|
| 35 |
+
cmdline::parser parser;
|
| 36 |
+
parser.add<std::string>("ienc", 0, "encoder model(onnx model or axmodel)", true, "cnclip/cnclip_vit_l14_336px_vision_u16u8.axmodel");
|
| 37 |
+
parser.add<std::string>("tenc", 0, "text encoder model(onnx model or axmodel)", true, "cnclip/cnclip_vit_l14_336px_text_u16.axmodel");
|
| 38 |
+
parser.add<std::string>("vocab", 'v', "vocab path", true, "cnclip/cn_vocab.txt");
|
| 39 |
+
parser.add<int>("language", 'l', "language choose, 0:english 1:chinese", false, 1);
|
| 40 |
+
parser.add<std::string>("db_path", 'd', "db path", false, "clip_feat_db");
|
| 41 |
+
|
| 42 |
+
parser.add<std::string>("image", 'i', "image folder(jpg png etc....)", true);
|
| 43 |
+
parser.add<std::string>("text", 't', "text or txt file", true);
|
| 44 |
+
parser.parse_check(argc, argv);
|
| 45 |
+
|
| 46 |
+
sprintf(init_info.image_encoder_path, "%s", parser.get<std::string>("ienc").c_str());
|
| 47 |
+
sprintf(init_info.text_encoder_path, "%s", parser.get<std::string>("tenc").c_str());
|
| 48 |
+
sprintf(init_info.tokenizer_path, "%s", parser.get<std::string>("vocab").c_str());
|
| 49 |
+
init_info.isCN = parser.get<int>("language");
|
| 50 |
+
sprintf(init_info.db_path, "%s", parser.get<std::string>("db_path").c_str());
|
| 51 |
+
|
| 52 |
+
printf("image_encoder_path: %s\n", init_info.image_encoder_path);
|
| 53 |
+
printf("text_encoder_path: %s\n", init_info.text_encoder_path);
|
| 54 |
+
printf("tokenizer_path: %s\n", init_info.tokenizer_path);
|
| 55 |
+
printf("isCN: %d\n", init_info.isCN);
|
| 56 |
+
printf("db_path: %s\n", init_info.db_path);
|
| 57 |
+
|
| 58 |
+
if (clip_devices.host.available)
|
| 59 |
+
{
|
| 60 |
+
init_info.dev_type = host_device;
|
| 61 |
+
}
|
| 62 |
+
else if (clip_devices.devices.count > 0)
|
| 63 |
+
{
|
| 64 |
+
init_info.dev_type = axcl_device;
|
| 65 |
+
init_info.devid = 0;
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
clip_handle_t handle;
|
| 69 |
+
int ret = clip_create(&init_info, &handle);
|
| 70 |
+
if (ret != clip_errcode_success)
|
| 71 |
+
{
|
| 72 |
+
printf("clip_create failed\n");
|
| 73 |
+
return -1;
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
std::string image_src = parser.get<std::string>("image");
|
| 77 |
+
std::string text = parser.get<std::string>("text");
|
| 78 |
+
|
| 79 |
+
std::vector<std::string> image_paths;
|
| 80 |
+
cv::glob(image_src + "/*.*", image_paths);
|
| 81 |
+
|
| 82 |
+
for (size_t i = 0; i < image_paths.size(); i++)
|
| 83 |
+
{
|
| 84 |
+
std::string image_path = image_paths[i];
|
| 85 |
+
std::string image_name = image_path.substr(image_path.find_last_of("/") + 1);
|
| 86 |
+
char key[CLIP_KEY_MAX_LEN];
|
| 87 |
+
sprintf(key, "%s", image_name.c_str());
|
| 88 |
+
if (clip_contain(handle, key))
|
| 89 |
+
{
|
| 90 |
+
// printf("%s is exist %04ld/%04ld\n", key, i, image_paths.size());
|
| 91 |
+
continue;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
cv::Mat src = cv::imread(image_path);
|
| 95 |
+
cv::cvtColor(src, src, cv::COLOR_BGR2RGB);
|
| 96 |
+
clip_image_t image;
|
| 97 |
+
image.data = src.data;
|
| 98 |
+
image.width = src.cols;
|
| 99 |
+
image.height = src.rows;
|
| 100 |
+
image.channels = src.channels();
|
| 101 |
+
image.stride = src.step;
|
| 102 |
+
|
| 103 |
+
timer t;
|
| 104 |
+
clip_add(handle, key, &image, 0);
|
| 105 |
+
// printf("add image %s %04ld/%04ld %6.2fms\n", image_name.c_str(), i, image_paths.size(), t.cost());
|
| 106 |
+
}
|
| 107 |
+
int topk = 10;
|
| 108 |
+
std::vector<clip_result_item_t> results(topk);
|
| 109 |
+
timer t;
|
| 110 |
+
clip_match_text(handle, text.c_str(), results.data(), topk);
|
| 111 |
+
printf("match text \"%s\" %6.2fms\n", text.c_str(), t.cost());
|
| 112 |
+
printf("|%32s | %6s|\n", "key", "score");
|
| 113 |
+
for (size_t i = 0; i < results.size(); i++)
|
| 114 |
+
{
|
| 115 |
+
printf("|%32s | %6.2f|\n", results[i].key, results[i].score);
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
clip_destroy(handle);
|
| 119 |
+
|
| 120 |
+
if (clip_devices.host.available)
|
| 121 |
+
{
|
| 122 |
+
clip_sys_deinit(host_device, -1);
|
| 123 |
+
}
|
| 124 |
+
else if (clip_devices.devices.count > 0)
|
| 125 |
+
{
|
| 126 |
+
|
| 127 |
+
clip_sys_deinit(axcl_device, 0);
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
+
return 0;
|
| 131 |
+
}
|
install/examples/timer.hpp
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*
|
| 2 |
+
* AXERA is pleased to support the open source community by making ax-samples available.
|
| 3 |
+
*
|
| 4 |
+
* Copyright (c) 2022, AXERA Semiconductor (Shanghai) Co., Ltd. All rights reserved.
|
| 5 |
+
*
|
| 6 |
+
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
|
| 7 |
+
* in compliance with the License. You may obtain a copy of the License at
|
| 8 |
+
*
|
| 9 |
+
* https://opensource.org/licenses/BSD-3-Clause
|
| 10 |
+
*
|
| 11 |
+
* Unless required by applicable law or agreed to in writing, software distributed
|
| 12 |
+
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
| 13 |
+
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
| 14 |
+
* specific language governing permissions and limitations under the License.
|
| 15 |
+
*/
|
| 16 |
+
|
| 17 |
+
/*
|
| 18 |
+
* Author: ls.wang
|
| 19 |
+
*/
|
| 20 |
+
|
| 21 |
+
#pragma once
|
| 22 |
+
|
| 23 |
+
#include <chrono>
|
| 24 |
+
|
| 25 |
+
class timer
|
| 26 |
+
{
|
| 27 |
+
private:
|
| 28 |
+
std::chrono::system_clock::time_point start_time, end_time;
|
| 29 |
+
|
| 30 |
+
public:
|
| 31 |
+
timer()
|
| 32 |
+
{
|
| 33 |
+
start();
|
| 34 |
+
}
|
| 35 |
+
|
| 36 |
+
void start()
|
| 37 |
+
{
|
| 38 |
+
stop();
|
| 39 |
+
this->start_time = this->end_time;
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
void stop()
|
| 43 |
+
{
|
| 44 |
+
#ifdef _MSC_VER
|
| 45 |
+
this->end_time = std::chrono::system_clock::now();
|
| 46 |
+
#else
|
| 47 |
+
this->end_time = std::chrono::high_resolution_clock::now();
|
| 48 |
+
#endif
|
| 49 |
+
}
|
| 50 |
+
|
| 51 |
+
float cost()
|
| 52 |
+
{
|
| 53 |
+
if (this->end_time <= this->start_time)
|
| 54 |
+
{
|
| 55 |
+
this->stop();
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
auto ms = std::chrono::duration_cast<std::chrono::microseconds>(this->end_time - this->start_time).count();
|
| 59 |
+
return static_cast<float>(ms) / 1000.f;
|
| 60 |
+
}
|
| 61 |
+
};
|
install/include/clip.h
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#ifndef __CLIP_H__
|
| 2 |
+
#define __CLIP_H__
|
| 3 |
+
|
| 4 |
+
#if defined(__cplusplus)
|
| 5 |
+
extern "C"
|
| 6 |
+
{
|
| 7 |
+
#endif
|
| 8 |
+
#define CLIP_DEVICES_COUNT 16
|
| 9 |
+
#define CLIP_VERSION_LEN 32
|
| 10 |
+
#define CLIP_KEY_MAX_LEN 64
|
| 11 |
+
#define CLIP_PATH_LEN 128
|
| 12 |
+
|
| 13 |
+
typedef enum
|
| 14 |
+
{
|
| 15 |
+
clip_errcode_failed = -1,
|
| 16 |
+
clip_errcode_success = 0,
|
| 17 |
+
|
| 18 |
+
clip_errcode_invalid_ptr,
|
| 19 |
+
clip_errcode_sysinit_failed,
|
| 20 |
+
clip_errcode_sysdeinit_failed,
|
| 21 |
+
clip_errcode_axcl_sysinit_failed,
|
| 22 |
+
clip_errcode_axcl_sysdeinit_failed,
|
| 23 |
+
|
| 24 |
+
clip_errcode_create_failed = 0x10000,
|
| 25 |
+
clip_errcode_create_failed_sys,
|
| 26 |
+
clip_errcode_create_failed_ienc,
|
| 27 |
+
clip_errcode_create_failed_tenc,
|
| 28 |
+
clip_errcode_create_failed_vocab,
|
| 29 |
+
clip_errcode_create_failed_db,
|
| 30 |
+
|
| 31 |
+
clip_errcode_destroy_failed = 0x20000,
|
| 32 |
+
|
| 33 |
+
clip_errcode_add_failed = 0x30000,
|
| 34 |
+
clip_errcode_add_failed_key_exist,
|
| 35 |
+
clip_errcode_add_failed_encode_image,
|
| 36 |
+
clip_errcode_add_failed_push_db,
|
| 37 |
+
|
| 38 |
+
clip_errcode_remove_failed = 0x40000,
|
| 39 |
+
clip_errcode_remove_failed_key_not_exist,
|
| 40 |
+
clip_errcode_remove_failed_del_db,
|
| 41 |
+
|
| 42 |
+
clip_errcode_match_failed = 0x50000,
|
| 43 |
+
clip_errcode_match_failed_encode_text,
|
| 44 |
+
clip_errcode_match_failed_encode_image,
|
| 45 |
+
} clip_errcode_e;
|
| 46 |
+
|
| 47 |
+
typedef enum
|
| 48 |
+
{
|
| 49 |
+
unknown_device = 0,
|
| 50 |
+
host_device = 1,
|
| 51 |
+
axcl_device = 2
|
| 52 |
+
} clip_devive_e;
|
| 53 |
+
|
| 54 |
+
typedef void *clip_handle_t;
|
| 55 |
+
|
| 56 |
+
typedef struct
|
| 57 |
+
{
|
| 58 |
+
struct
|
| 59 |
+
{
|
| 60 |
+
char available;
|
| 61 |
+
char version[CLIP_VERSION_LEN];
|
| 62 |
+
struct
|
| 63 |
+
{
|
| 64 |
+
int remain;
|
| 65 |
+
int total;
|
| 66 |
+
} mem_info;
|
| 67 |
+
} host;
|
| 68 |
+
|
| 69 |
+
struct
|
| 70 |
+
{
|
| 71 |
+
char host_version[CLIP_VERSION_LEN];
|
| 72 |
+
char dev_version[CLIP_VERSION_LEN];
|
| 73 |
+
unsigned char count;
|
| 74 |
+
struct
|
| 75 |
+
{
|
| 76 |
+
int temp;
|
| 77 |
+
int cpu_usage;
|
| 78 |
+
int npu_usage;
|
| 79 |
+
struct
|
| 80 |
+
{
|
| 81 |
+
int remain;
|
| 82 |
+
int total;
|
| 83 |
+
} mem_info;
|
| 84 |
+
} devices_info[CLIP_DEVICES_COUNT];
|
| 85 |
+
|
| 86 |
+
} devices;
|
| 87 |
+
} clip_devices_t;
|
| 88 |
+
|
| 89 |
+
typedef struct
|
| 90 |
+
{
|
| 91 |
+
clip_devive_e dev_type; // Device type
|
| 92 |
+
char devid; // axcl device ID
|
| 93 |
+
char text_encoder_path[CLIP_PATH_LEN]; // Text encoder model path
|
| 94 |
+
char image_encoder_path[CLIP_PATH_LEN]; // Image encoder model path
|
| 95 |
+
char tokenizer_path[CLIP_PATH_LEN]; // Tokenizer model path
|
| 96 |
+
char isCN; // Whether it's a Chinese model (0: English, 1: Chinese)
|
| 97 |
+
char db_path[CLIP_PATH_LEN]; // Database path (if empty path is specified, a folder will be created)
|
| 98 |
+
} clip_init_t;
|
| 99 |
+
|
| 100 |
+
typedef struct
|
| 101 |
+
{
|
| 102 |
+
unsigned char *data;
|
| 103 |
+
int width;
|
| 104 |
+
int height;
|
| 105 |
+
int channels;
|
| 106 |
+
int stride;
|
| 107 |
+
} clip_image_t;
|
| 108 |
+
|
| 109 |
+
typedef struct
|
| 110 |
+
{
|
| 111 |
+
char key[CLIP_KEY_MAX_LEN];
|
| 112 |
+
float score;
|
| 113 |
+
} clip_result_item_t;
|
| 114 |
+
|
| 115 |
+
/**
|
| 116 |
+
* @brief Enumerate available devices in the current system
|
| 117 |
+
* @param devices Pointer to device information structure
|
| 118 |
+
* @return int Returns 0 on success, -1 on failure
|
| 119 |
+
*/
|
| 120 |
+
int clip_enum_devices(clip_devices_t *devices);
|
| 121 |
+
|
| 122 |
+
/**
|
| 123 |
+
* @brief Initialize CLIP system resources
|
| 124 |
+
* @param dev_type Device type
|
| 125 |
+
* @param devid Device ID
|
| 126 |
+
* @return clip_errcode_e Returns 0 on success, error codes see clip_errcode_e
|
| 127 |
+
*/
|
| 128 |
+
int clip_sys_init(clip_devive_e dev_type, char devid);
|
| 129 |
+
|
| 130 |
+
/**
|
| 131 |
+
* @brief Deinitialize CLIP system resources
|
| 132 |
+
* @param dev_type Device type
|
| 133 |
+
* @param devid Device ID
|
| 134 |
+
* @return clip_errcode_e Returns 0 on success, error codes see clip_errcode_e
|
| 135 |
+
*/
|
| 136 |
+
int clip_sys_deinit(clip_devive_e dev_type, char devid);
|
| 137 |
+
|
| 138 |
+
/**
|
| 139 |
+
* @brief Create CLIP handle
|
| 140 |
+
* @param init_info Pointer to initialization information structure
|
| 141 |
+
* @param handle Handle pointer
|
| 142 |
+
* @return clip_errcode_e Returns 0 on success, error codes see clip_errcode_e
|
| 143 |
+
*/
|
| 144 |
+
int clip_create(clip_init_t *init_info, clip_handle_t *handle);
|
| 145 |
+
|
| 146 |
+
/**
|
| 147 |
+
* @brief Destroy CLIP handle
|
| 148 |
+
* @param handle Handle
|
| 149 |
+
* @return clip_errcode_e Returns 0 on success, error codes see clip_errcode_e
|
| 150 |
+
*/
|
| 151 |
+
int clip_destroy(clip_handle_t handle);
|
| 152 |
+
|
| 153 |
+
/**
|
| 154 |
+
* @brief Add image to CLIP database
|
| 155 |
+
* @param handle Handle
|
| 156 |
+
* @param key Image key
|
| 157 |
+
* @param image Pointer to image structure
|
| 158 |
+
* @param overwrite Whether to overwrite
|
| 159 |
+
* @return clip_errcode_e Returns 0 on success, error codes see clip_errcode_e
|
| 160 |
+
*/
|
| 161 |
+
int clip_add(clip_handle_t handle, char key[CLIP_KEY_MAX_LEN], clip_image_t *image, char overwrite);
|
| 162 |
+
|
| 163 |
+
/**
|
| 164 |
+
* @brief Remove image from CLIP database
|
| 165 |
+
* @param handle Handle
|
| 166 |
+
* @param key Image key
|
| 167 |
+
* @return clip_errcode_e Returns 0 on success, error codes see clip_errcode_e
|
| 168 |
+
*/
|
| 169 |
+
int clip_remove(clip_handle_t handle, char key[CLIP_KEY_MAX_LEN]);
|
| 170 |
+
|
| 171 |
+
/**
|
| 172 |
+
* @brief Check if image exists in CLIP database
|
| 173 |
+
* @param handle Handle
|
| 174 |
+
* @param key Image key
|
| 175 |
+
* @return clip_errcode_e Returns 0 on success, error codes see clip_errcode_e
|
| 176 |
+
*/
|
| 177 |
+
int clip_contain(clip_handle_t handle, char key[CLIP_KEY_MAX_LEN]);
|
| 178 |
+
|
| 179 |
+
/**
|
| 180 |
+
* @brief Text match CLIP database images (softmax)
|
| 181 |
+
* @param handle Handle
|
| 182 |
+
* @param text Text
|
| 183 |
+
* @param results Pointer to result structure
|
| 184 |
+
* @param top_k Top k results
|
| 185 |
+
* @return clip_errcode_e Returns 0 on success, error codes see clip_errcode_e
|
| 186 |
+
*/
|
| 187 |
+
int clip_match_text(clip_handle_t handle, const char *text, clip_result_item_t *results, int top_k);
|
| 188 |
+
|
| 189 |
+
/**
|
| 190 |
+
* @brief Image match CLIP database images (cosine similarity)
|
| 191 |
+
* @param handle Handle
|
| 192 |
+
* @param image Pointer to image structure
|
| 193 |
+
* @param results Pointer to result structure
|
| 194 |
+
* @param top_k Top k results
|
| 195 |
+
* @return clip_errcode_e Returns 0 on success, error codes see clip_errcode_e
|
| 196 |
+
*/
|
| 197 |
+
int clip_match_image(clip_handle_t handle, clip_image_t *image, clip_result_item_t *results, int top_k);
|
| 198 |
+
|
| 199 |
+
#if defined(__cplusplus)
|
| 200 |
+
}
|
| 201 |
+
#endif
|
| 202 |
+
|
| 203 |
+
#endif // __CLIP_H__
|
install/lib/aarch64/libclip.so
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:4d26c8940d14c0d749ece83b4be6ed13eb86487c31acb0c7591fffb6e21fe3ad
|
| 3 |
+
size 4309856
|
pyclip/example.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from pyclip import Clip, enum_devices, sys_init, sys_deinit, ClipDeviceType
|
| 3 |
+
import cv2
|
| 4 |
+
import glob
|
| 5 |
+
import argparse
|
| 6 |
+
import tqdm
|
| 7 |
+
|
| 8 |
+
if __name__ == '__main__':
|
| 9 |
+
parser = argparse.ArgumentParser()
|
| 10 |
+
parser.add_argument('--ienc', type=str, default='cnclip/cnclip_vit_l14_336px_vision_u16u8.axmodel')
|
| 11 |
+
parser.add_argument('--tenc', type=str, default='cnclip/cnclip_vit_l14_336px_text_u16.axmodel')
|
| 12 |
+
parser.add_argument('--vocab', type=str, default='cnclip/cn_vocab.txt')
|
| 13 |
+
parser.add_argument('--isCN', type=int, default=1)
|
| 14 |
+
parser.add_argument('--db_path', type=str, default='clip_feat_db_coco')
|
| 15 |
+
parser.add_argument('--image_folder', type=str, default='coco_1000')
|
| 16 |
+
args = parser.parse_args()
|
| 17 |
+
|
| 18 |
+
image_folder = args.image_folder
|
| 19 |
+
|
| 20 |
+
# 枚举设备
|
| 21 |
+
print("可用设备:", enum_devices())
|
| 22 |
+
|
| 23 |
+
# 初始化系统
|
| 24 |
+
sys_init(ClipDeviceType.axcl_device, 0)
|
| 25 |
+
|
| 26 |
+
try:
|
| 27 |
+
# 创建CLIP实例
|
| 28 |
+
clip = Clip({
|
| 29 |
+
'text_encoder_path': args.tenc,
|
| 30 |
+
'image_encoder_path': args.ienc,
|
| 31 |
+
'tokenizer_path': args.vocab,
|
| 32 |
+
'db_path': args.db_path,
|
| 33 |
+
'isCN': args.isCN
|
| 34 |
+
})
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
# 添加图像
|
| 38 |
+
image_files = glob.glob(os.path.join(image_folder, '*.jpg'))
|
| 39 |
+
for image_file in tqdm.tqdm(image_files):
|
| 40 |
+
img = cv2.imread(image_file)
|
| 41 |
+
cv2.cvtColor(img, cv2.COLOR_BGR2RGB, img)
|
| 42 |
+
filename = os.path.basename(image_file)
|
| 43 |
+
clip.add_image(filename, img)
|
| 44 |
+
|
| 45 |
+
# 文本匹配
|
| 46 |
+
results = clip.match_text('dog', top_k=10)
|
| 47 |
+
print("匹配结果:", results)
|
| 48 |
+
|
| 49 |
+
finally:
|
| 50 |
+
# 反初始化系统
|
| 51 |
+
sys_deinit(ClipDeviceType.axcl_device, 0)
|
pyclip/gradio_example.png
ADDED
|
Git LFS Details
|
pyclip/gradio_example.py
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import gradio as gr
|
| 3 |
+
from pyclip import Clip, enum_devices, sys_init, sys_deinit, ClipDeviceType
|
| 4 |
+
import cv2
|
| 5 |
+
import glob
|
| 6 |
+
from PIL import Image
|
| 7 |
+
import tqdm
|
| 8 |
+
import argparse
|
| 9 |
+
|
| 10 |
+
if __name__ == '__main__':
|
| 11 |
+
parser = argparse.ArgumentParser()
|
| 12 |
+
parser.add_argument('--ienc', type=str, default='cnclip/cnclip_vit_l14_336px_vision_u16u8.axmodel')
|
| 13 |
+
parser.add_argument('--tenc', type=str, default='cnclip/cnclip_vit_l14_336px_text_u16.axmodel')
|
| 14 |
+
parser.add_argument('--vocab', type=str, default='cnclip/cn_vocab.txt')
|
| 15 |
+
parser.add_argument('--isCN', type=int, default=1)
|
| 16 |
+
parser.add_argument('--db_path', type=str, default='clip_feat_db_coco')
|
| 17 |
+
parser.add_argument('--image_folder', type=str, default='coco_1000')
|
| 18 |
+
args = parser.parse_args()
|
| 19 |
+
|
| 20 |
+
image_folder = args.image_folder
|
| 21 |
+
|
| 22 |
+
# 初始化
|
| 23 |
+
print("可用设备:", enum_devices())
|
| 24 |
+
sys_init(ClipDeviceType.axcl_device, 0)
|
| 25 |
+
|
| 26 |
+
clip = Clip({
|
| 27 |
+
'text_encoder_path': args.tenc,
|
| 28 |
+
'image_encoder_path': args.ienc,
|
| 29 |
+
'tokenizer_path': args.vocab,
|
| 30 |
+
'db_path': args.db_path,
|
| 31 |
+
'isCN': args.isCN
|
| 32 |
+
})
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
# 加载图片数据库(只做一次)
|
| 36 |
+
image_files = glob.glob(os.path.join(image_folder, '*.jpg'))
|
| 37 |
+
for image_file in tqdm.tqdm(image_files):
|
| 38 |
+
filename = os.path.basename(image_file)
|
| 39 |
+
if clip.contains_image(filename) == 1:
|
| 40 |
+
continue
|
| 41 |
+
img = cv2.imread(image_file)
|
| 42 |
+
cv2.cvtColor(img, cv2.COLOR_BGR2RGB, img)
|
| 43 |
+
clip.add_image(filename, img)
|
| 44 |
+
|
| 45 |
+
# 工具函数:图片转 base64
|
| 46 |
+
def img_to_pil(img_path):
|
| 47 |
+
return Image.open(img_path).convert("RGB")
|
| 48 |
+
|
| 49 |
+
# 主搜索函数
|
| 50 |
+
def search_images(query, top_k):
|
| 51 |
+
results = clip.match_text(query, top_k=top_k)
|
| 52 |
+
images = []
|
| 53 |
+
for filename, score in results:
|
| 54 |
+
img_path = os.path.join(image_folder, filename)
|
| 55 |
+
if os.path.exists(img_path):
|
| 56 |
+
img = img_to_pil(img_path)
|
| 57 |
+
images.append((img, f"{filename} Score: {score:.4f}"))
|
| 58 |
+
return images
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
# Gradio界面
|
| 62 |
+
with gr.Blocks() as demo:
|
| 63 |
+
gr.Markdown("# 🔍 文搜图 Demo")
|
| 64 |
+
|
| 65 |
+
with gr.Row():
|
| 66 |
+
query_input = gr.Textbox(label="请输入文本查询")
|
| 67 |
+
topk_input = gr.Number(value=25, precision=0, label="Top-K")
|
| 68 |
+
search_btn = gr.Button("搜图")
|
| 69 |
+
|
| 70 |
+
gallery = gr.Gallery(label="匹配结果", show_label=True, columns=4)
|
| 71 |
+
|
| 72 |
+
search_btn.click(fn=search_images, inputs=[query_input, topk_input], outputs=gallery)
|
| 73 |
+
|
| 74 |
+
# 启动
|
| 75 |
+
ip = "0.0.0.0"
|
| 76 |
+
demo.launch(server_name=ip, server_port=7860)
|
| 77 |
+
|
| 78 |
+
# 关闭系统(你可加信号处理来自动关闭)
|
| 79 |
+
import atexit
|
| 80 |
+
atexit.register(lambda: sys_deinit(ClipDeviceType.axcl_device, 0))
|
pyclip/pyclip.py
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import ctypes
|
| 2 |
+
import os
|
| 3 |
+
from typing import List, Tuple, Optional
|
| 4 |
+
import numpy as np
|
| 5 |
+
import platform
|
| 6 |
+
|
| 7 |
+
base_dir = os.path.dirname(__file__)
|
| 8 |
+
arch = platform.machine()
|
| 9 |
+
|
| 10 |
+
if arch == 'x86_64':
|
| 11 |
+
arch_dir = 'x86_64'
|
| 12 |
+
elif arch in ('aarch64', 'arm64'):
|
| 13 |
+
arch_dir = 'aarch64'
|
| 14 |
+
else:
|
| 15 |
+
raise RuntimeError(f"Unsupported architecture: {arch}")
|
| 16 |
+
|
| 17 |
+
lib_paths = [
|
| 18 |
+
os.path.join(base_dir, arch_dir, 'libclip.so'),
|
| 19 |
+
os.path.join(base_dir, 'libclip.so')
|
| 20 |
+
]
|
| 21 |
+
|
| 22 |
+
last_error = None
|
| 23 |
+
diagnostic_shown = set()
|
| 24 |
+
|
| 25 |
+
for lib_path in lib_paths:
|
| 26 |
+
try:
|
| 27 |
+
print(f"Trying to load: {lib_path}")
|
| 28 |
+
_lib = ctypes.CDLL(lib_path)
|
| 29 |
+
print(f"✅ Successfully loaded: {lib_path}")
|
| 30 |
+
break
|
| 31 |
+
except OSError as e:
|
| 32 |
+
last_error = e
|
| 33 |
+
err_str = str(e)
|
| 34 |
+
print(f"\n❌ Failed to load: {lib_path}")
|
| 35 |
+
print(f" {err_str}")
|
| 36 |
+
|
| 37 |
+
# Only show GLIBCXX tip once
|
| 38 |
+
if "GLIBCXX" in err_str and "not found" in err_str:
|
| 39 |
+
if "missing_glibcxx" not in diagnostic_shown:
|
| 40 |
+
diagnostic_shown.add("missing_glibcxx")
|
| 41 |
+
print("🔍 Detected missing GLIBCXX version in libstdc++.so.6")
|
| 42 |
+
print("💡 This usually happens when your environment (like Conda) uses an older libstdc++")
|
| 43 |
+
print(f"👉 Try running with system libstdc++ preloaded:")
|
| 44 |
+
print(f" export LD_PRELOAD=/usr/lib/{arch_dir}-linux-gnu/libstdc++.so.6\n")
|
| 45 |
+
elif "No such file" in err_str:
|
| 46 |
+
if "file_not_found" not in diagnostic_shown:
|
| 47 |
+
diagnostic_shown.add("file_not_found")
|
| 48 |
+
print("🔍 File not found. Please verify that libclip.so exists and the path is correct.\n")
|
| 49 |
+
elif "wrong ELF class" in err_str:
|
| 50 |
+
if "elf_mismatch" not in diagnostic_shown:
|
| 51 |
+
diagnostic_shown.add("elf_mismatch")
|
| 52 |
+
print("🔍 ELF class mismatch — likely due to architecture conflict (e.g., loading x86_64 .so on aarch64).")
|
| 53 |
+
print(f"👉 Run `file {lib_path}` to verify the binary architecture.\n")
|
| 54 |
+
else:
|
| 55 |
+
if "generic_error" not in diagnostic_shown:
|
| 56 |
+
diagnostic_shown.add("generic_error")
|
| 57 |
+
print("📎 Tip: Use `ldd` to inspect missing dependencies:")
|
| 58 |
+
print(f" ldd {lib_path}\n")
|
| 59 |
+
else:
|
| 60 |
+
raise RuntimeError(f"\n❗ Failed to load libclip.so.\nLast error:\n{last_error}")
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
# 定义枚举类型
|
| 64 |
+
class ClipDeviceType(ctypes.c_int):
|
| 65 |
+
unknown_device = 0
|
| 66 |
+
host_device = 1
|
| 67 |
+
axcl_device = 2
|
| 68 |
+
|
| 69 |
+
# 定义结构体
|
| 70 |
+
class ClipMemInfo(ctypes.Structure):
|
| 71 |
+
_fields_ = [
|
| 72 |
+
('remain', ctypes.c_int),
|
| 73 |
+
('total', ctypes.c_int)
|
| 74 |
+
]
|
| 75 |
+
|
| 76 |
+
class ClipHostInfo(ctypes.Structure):
|
| 77 |
+
_fields_ = [
|
| 78 |
+
('available', ctypes.c_char),
|
| 79 |
+
('version', ctypes.c_char * 32),
|
| 80 |
+
('mem_info', ClipMemInfo)
|
| 81 |
+
]
|
| 82 |
+
|
| 83 |
+
class ClipDeviceInfo(ctypes.Structure):
|
| 84 |
+
_fields_ = [
|
| 85 |
+
('temp', ctypes.c_int),
|
| 86 |
+
('cpu_usage', ctypes.c_int),
|
| 87 |
+
('npu_usage', ctypes.c_int),
|
| 88 |
+
('mem_info', ClipMemInfo)
|
| 89 |
+
]
|
| 90 |
+
|
| 91 |
+
class ClipDevices(ctypes.Structure):
|
| 92 |
+
_fields_ = [
|
| 93 |
+
('host', ClipHostInfo),
|
| 94 |
+
('host_version', ctypes.c_char * 32),
|
| 95 |
+
('dev_version', ctypes.c_char * 32),
|
| 96 |
+
('count', ctypes.c_ubyte),
|
| 97 |
+
('devices_info', ClipDeviceInfo * 16)
|
| 98 |
+
]
|
| 99 |
+
|
| 100 |
+
class ClipInit(ctypes.Structure):
|
| 101 |
+
_fields_ = [
|
| 102 |
+
('dev_type', ClipDeviceType),
|
| 103 |
+
('devid', ctypes.c_char),
|
| 104 |
+
('text_encoder_path', ctypes.c_char * 128),
|
| 105 |
+
('image_encoder_path', ctypes.c_char * 128),
|
| 106 |
+
('tokenizer_path', ctypes.c_char * 128),
|
| 107 |
+
('isCN', ctypes.c_char),
|
| 108 |
+
('db_path', ctypes.c_char * 128)
|
| 109 |
+
]
|
| 110 |
+
|
| 111 |
+
class ClipImage(ctypes.Structure):
|
| 112 |
+
_fields_ = [
|
| 113 |
+
('data', ctypes.POINTER(ctypes.c_ubyte)),
|
| 114 |
+
('width', ctypes.c_int),
|
| 115 |
+
('height', ctypes.c_int),
|
| 116 |
+
('channels', ctypes.c_int),
|
| 117 |
+
('stride', ctypes.c_int)
|
| 118 |
+
]
|
| 119 |
+
|
| 120 |
+
class ClipResultItem(ctypes.Structure):
|
| 121 |
+
_fields_ = [
|
| 122 |
+
('key', ctypes.c_char * 64),
|
| 123 |
+
('score', ctypes.c_float)
|
| 124 |
+
]
|
| 125 |
+
|
| 126 |
+
# 设置函数参数和返回类型
|
| 127 |
+
_lib.clip_enum_devices.argtypes = [ctypes.POINTER(ClipDevices)]
|
| 128 |
+
_lib.clip_enum_devices.restype = ctypes.c_int
|
| 129 |
+
|
| 130 |
+
_lib.clip_sys_init.argtypes = [ClipDeviceType, ctypes.c_char]
|
| 131 |
+
_lib.clip_sys_init.restype = ctypes.c_int
|
| 132 |
+
|
| 133 |
+
_lib.clip_sys_deinit.argtypes = [ClipDeviceType, ctypes.c_char]
|
| 134 |
+
_lib.clip_sys_deinit.restype = ctypes.c_int
|
| 135 |
+
|
| 136 |
+
_lib.clip_create.argtypes = [ctypes.POINTER(ClipInit), ctypes.POINTER(ctypes.c_void_p)]
|
| 137 |
+
_lib.clip_create.restype = ctypes.c_int
|
| 138 |
+
|
| 139 |
+
_lib.clip_destroy.argtypes = [ctypes.c_void_p]
|
| 140 |
+
_lib.clip_destroy.restype = ctypes.c_int
|
| 141 |
+
|
| 142 |
+
_lib.clip_add.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.POINTER(ClipImage), ctypes.c_char]
|
| 143 |
+
_lib.clip_add.restype = ctypes.c_int
|
| 144 |
+
|
| 145 |
+
_lib.clip_remove.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
|
| 146 |
+
_lib.clip_remove.restype = ctypes.c_int
|
| 147 |
+
|
| 148 |
+
_lib.clip_contain.argtypes = [ctypes.c_void_p, ctypes.c_char_p]
|
| 149 |
+
_lib.clip_contain.restype = ctypes.c_int
|
| 150 |
+
|
| 151 |
+
_lib.clip_match_text.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.POINTER(ClipResultItem), ctypes.c_int]
|
| 152 |
+
_lib.clip_match_text.restype = ctypes.c_int
|
| 153 |
+
|
| 154 |
+
_lib.clip_match_image.argtypes = [ctypes.c_void_p, ctypes.POINTER(ClipImage), ctypes.POINTER(ClipResultItem), ctypes.c_int]
|
| 155 |
+
_lib.clip_match_image.restype = ctypes.c_int
|
| 156 |
+
|
| 157 |
+
class ClipError(Exception):
|
| 158 |
+
pass
|
| 159 |
+
|
| 160 |
+
def check_error(code: int) -> None:
|
| 161 |
+
if code != 0:
|
| 162 |
+
raise ClipError(f"CLIP API错误: {code}")
|
| 163 |
+
|
| 164 |
+
class Clip:
|
| 165 |
+
def __init__(self, init_info: dict):
|
| 166 |
+
self.handle = None
|
| 167 |
+
self.init_info = ClipInit()
|
| 168 |
+
|
| 169 |
+
# 设置初始化参数
|
| 170 |
+
self.init_info.dev_type = init_info.get('dev_type', ClipDeviceType.axcl_device)
|
| 171 |
+
self.init_info.devid = init_info.get('devid', 0)
|
| 172 |
+
self.init_info.isCN = init_info.get('isCN', 1)
|
| 173 |
+
|
| 174 |
+
# 设置路径
|
| 175 |
+
for path_name in ['text_encoder_path', 'image_encoder_path', 'tokenizer_path', 'db_path']:
|
| 176 |
+
if path_name in init_info:
|
| 177 |
+
setattr(self.init_info, path_name, init_info[path_name].encode('utf-8'))
|
| 178 |
+
|
| 179 |
+
# 创建CLIP实例
|
| 180 |
+
handle = ctypes.c_void_p()
|
| 181 |
+
check_error(_lib.clip_create(ctypes.byref(self.init_info), ctypes.byref(handle)))
|
| 182 |
+
self.handle = handle
|
| 183 |
+
|
| 184 |
+
def __del__(self):
|
| 185 |
+
if self.handle:
|
| 186 |
+
_lib.clip_destroy(self.handle)
|
| 187 |
+
|
| 188 |
+
def add_image(self, key: str, image_data: np.ndarray) -> None:
|
| 189 |
+
if self.contains_image(key):
|
| 190 |
+
return
|
| 191 |
+
image = ClipImage()
|
| 192 |
+
image.data = ctypes.cast(image_data.ctypes.data, ctypes.POINTER(ctypes.c_ubyte))
|
| 193 |
+
image.width = image_data.shape[1]
|
| 194 |
+
image.height = image_data.shape[0]
|
| 195 |
+
image.channels = image_data.shape[2]
|
| 196 |
+
image.stride = image_data.shape[1] * image_data.shape[2]
|
| 197 |
+
|
| 198 |
+
check_error(_lib.clip_add(self.handle, key.encode('utf-8'), ctypes.byref(image), 0))
|
| 199 |
+
|
| 200 |
+
def remove_image(self, key: str) -> None:
|
| 201 |
+
check_error(_lib.clip_remove(self.handle, key.encode('utf-8')))
|
| 202 |
+
|
| 203 |
+
def contains_image(self, key: str) -> bool:
|
| 204 |
+
return _lib.clip_contain(self.handle, key.encode('utf-8')) == 1
|
| 205 |
+
|
| 206 |
+
def match_text(self, text: str, top_k: int = 10) -> List[Tuple[str, float]]:
|
| 207 |
+
results = (ClipResultItem * top_k)()
|
| 208 |
+
check_error(_lib.clip_match_text(self.handle, text.encode('utf-8'), results, top_k))
|
| 209 |
+
|
| 210 |
+
return [(item.key.decode('utf-8'), item.score) for item in results]
|
| 211 |
+
|
| 212 |
+
def match_image(self, image_data: bytes, width: int, height: int, channels: int = 3, top_k: int = 10) -> List[Tuple[str, float]]:
|
| 213 |
+
image = ClipImage()
|
| 214 |
+
image.data = ctypes.cast(ctypes.create_string_buffer(image_data), ctypes.POINTER(ctypes.c_ubyte))
|
| 215 |
+
image.width = width
|
| 216 |
+
image.height = height
|
| 217 |
+
image.channels = channels
|
| 218 |
+
image.stride = width * channels
|
| 219 |
+
|
| 220 |
+
results = (ClipResultItem * top_k)()
|
| 221 |
+
check_error(_lib.clip_match_image(self.handle, ctypes.byref(image), ctypes.byref(results), top_k))
|
| 222 |
+
|
| 223 |
+
return [(item.key.decode('utf-8'), item.score) for item in results]
|
| 224 |
+
|
| 225 |
+
def enum_devices() -> dict:
|
| 226 |
+
devices = ClipDevices()
|
| 227 |
+
check_error(_lib.clip_enum_devices(ctypes.byref(devices)))
|
| 228 |
+
|
| 229 |
+
return {
|
| 230 |
+
'host': {
|
| 231 |
+
'available': bool(devices.host.available),
|
| 232 |
+
'version': devices.host.version.decode('utf-8'),
|
| 233 |
+
'mem_info': {
|
| 234 |
+
'remain': devices.host.mem_info.remain,
|
| 235 |
+
'total': devices.host.mem_info.total
|
| 236 |
+
}
|
| 237 |
+
},
|
| 238 |
+
'devices': {
|
| 239 |
+
'host_version': devices.host_version.decode('utf-8'),
|
| 240 |
+
'dev_version': devices.dev_version.decode('utf-8'),
|
| 241 |
+
'count': devices.count,
|
| 242 |
+
'devices_info': [{
|
| 243 |
+
'temp': dev.temp,
|
| 244 |
+
'cpu_usage': dev.cpu_usage,
|
| 245 |
+
'npu_usage': dev.npu_usage,
|
| 246 |
+
'mem_info': {
|
| 247 |
+
'remain': dev.mem_info.remain,
|
| 248 |
+
'total': dev.mem_info.total
|
| 249 |
+
}
|
| 250 |
+
} for dev in devices.devices_info[:devices.count]]
|
| 251 |
+
}
|
| 252 |
+
}
|
| 253 |
+
|
| 254 |
+
|
| 255 |
+
def sys_init(dev_type: ClipDeviceType = ClipDeviceType.axcl_device, devid: int = 0) -> None:
|
| 256 |
+
check_error(_lib.clip_sys_init(dev_type, devid))
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
def sys_deinit(dev_type: ClipDeviceType = ClipDeviceType.axcl_device, devid: int = 0) -> None:
|
| 260 |
+
check_error(_lib.clip_sys_deinit(dev_type, devid))
|
pyclip/requirements.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio
|
| 2 |
+
opencv-python
|
| 3 |
+
tqdm
|
| 4 |
+
Pillow
|