ref(upstream): FULL TREE — Deep-Spark xllm (1470) + ds_vllm csrc/models (703)
Replaces cherry-picked upstream_ref with complete source trees. xllm/ — Iluvatar official C++ inference engine (15MB, 1470 files) Complete: kernels → layers → models → runtime → scheduler → api Excluded: .git, binary images, third_party submodule checkouts ds_vllm/ — Iluvatar official vllm fork (8MB, 703 files) Included: csrc/ (ALL CUDA kernels), fused_moe/, qwen3_5 model, _custom_ops Excluded: tests, benchmarks, docs, examples (not needed for reference) Critical call chains now fully traceable: MoE: moe_topk_softmax_kernels.cuh → ixformer.h → fused_moe.cpp → layer GDN: qwen3_gated_delta_net_base.cpp → qwen3_5_gated_delta_net.cpp Attention: ixformer.h → xllm_paged_attention → attention.cpp
This commit is contained in:
99
upstream_ref/xllm/docs/en/getting_started/disagg_pd.md
Normal file
99
upstream_ref/xllm/docs/en/getting_started/disagg_pd.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# PD disaggregation
|
||||
|
||||
`xllm` supports PD disaggregation deployment, which requires integration with our other open-source library [xllm service](https://github.com/jd-opensource/xllm-service).
|
||||
|
||||
## xLLM Service Dependencies
|
||||
|
||||
First, download and install `xllm service`, similar to installing and compiling `xllm`:
|
||||
```bash
|
||||
git clone https://github.com/jd-opensource/xllm-service
|
||||
cd xllm_service
|
||||
git submodule init
|
||||
git submodule update
|
||||
```
|
||||
|
||||
|
||||
### etcd Installation
|
||||
|
||||
`xllm_service` compilation and operation depend on [etcd](https://github.com/etcd-io/etcd).Use the [installation script](https://github.com/etcd-io/etcd/releases) provided by etcd for installation. The default installation path provided by the script is `/tmp/etcd-download-test/etcd`. You can either manually modify the installation path in the script or manually migrate after running the script:
|
||||
```bash
|
||||
mv /tmp/etcd-download-test/etcd /path/to/your/etcd
|
||||
```
|
||||
|
||||
### xLLM Service Compilation
|
||||
Apply patch:
|
||||
```bash
|
||||
sh prepare.sh
|
||||
```
|
||||
Then execute the compilation:
|
||||
```bash
|
||||
mkdir -p build
|
||||
cd build
|
||||
cmake ..
|
||||
make -j 8
|
||||
cd ..
|
||||
```
|
||||
|
||||
!!! warning "Potential Errors"
|
||||
You may encounter installation errors related to `boost-locale` and `boost-interprocess`: `vcpkg-src/packages/boost-locale_x64-linux/include: No such file or directory`, `/vcpkg-src/packages/boost-interprocess_x64-linux/include: No such file or directory`
|
||||
Reinstall these packages using `vcpkg`:
|
||||
```bash
|
||||
/path/to/vcpkg remove boost-locale boost-interprocess
|
||||
/path/to/vcpkg install boost-locale:x64-linux
|
||||
/path/to/vcpkg install boost-interprocess:x64-linux
|
||||
```
|
||||
|
||||
## PD Disaggregation Execution
|
||||
|
||||
Start etcd:
|
||||
```bash
|
||||
./etcd-download-test/etcd --listen-peer-urls 'http://localhost:2390' --listen-client-urls 'http://localhost:2389' --advertise-client-urls 'http://localhost:2391'
|
||||
```
|
||||
|
||||
Start xllm service:
|
||||
```bash
|
||||
ENABLE_DECODE_RESPONSE_TO_SERVICE=true ./xllm_master_serving --etcd_addr="127.0.0.1:12389" --http_server_port 28888 --rpc_server_port 28889 --tokenizer_path=/path/to/tokenizer_config_dir/
|
||||
```
|
||||
|
||||
Taking Qwen2-7B as an example:
|
||||
|
||||
- Start Prefill Instance
|
||||
```bash
|
||||
/path/to/xllm --model=path/to/Qwen2-7B-Instruct \
|
||||
--port=8010 \
|
||||
--devices="npu:0" \
|
||||
--master_node_addr="127.0.0.1:18888" \
|
||||
--enable_prefix_cache=false \
|
||||
--enable_chunked_prefill=false \
|
||||
--enable_disagg_pd=true \
|
||||
--instance_role=PREFILL \
|
||||
--etcd_addr=127.0.0.1:12389 \
|
||||
--transfer_listen_port=26000 \
|
||||
--disagg_pd_port=7777 \
|
||||
--node_rank=0 \
|
||||
--nnodes=1
|
||||
```
|
||||
- Start Decode Instance
|
||||
```bash
|
||||
/path/to/xllm --model=path/to/Qwen2-7B-Instruct \
|
||||
--port=8020 \
|
||||
--devices="npu:1" \
|
||||
--master_node_addr="127.0.0.1:18898" \
|
||||
--enable_prefix_cache=false \
|
||||
--enable_chunked_prefill=false \
|
||||
--enable_disagg_pd=true \
|
||||
--instance_role=DECODE \
|
||||
--etcd_addr=127.0.0.1:12389 \
|
||||
--transfer_listen_port=26100 \
|
||||
--disagg_pd_port=7787 \
|
||||
--node_rank=0 \
|
||||
--nnodes=1
|
||||
```
|
||||
|
||||
Important notes:
|
||||
|
||||
- PD disaggregation requires reading the `/etc/hccn.conf` file. Make sure this file on the physical machine is mapped into the container.
|
||||
|
||||
- `etcd_addr` must match the `etcd_addr` of `xllm_service`
|
||||
|
||||
The test command is similar to above. Note that the `PORT` in `curl http://localhost:{PORT}/v1/chat/completions ...` should be the `port` of the `http_server_port` of xLLM service.
|
||||
125
upstream_ref/xllm/docs/en/getting_started/launch_xllm.md
Normal file
125
upstream_ref/xllm/docs/en/getting_started/launch_xllm.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Launch xllm
|
||||
|
||||
Taking Qwen3 as an example, the script for launching xllm is as follows. The provided script is suitable for both single-node single-device and single-node multi-device scenarios. When using multiple devices on a single node, you need to modify `NNODES` (one device represents one node), as well as environment variables such as `ASCEND_RT_VISIBLE_DEVICES`, `CUDA_VISIBLE_DEVICES`, or `MLU_VISIBLE_DEVICES`.
|
||||
|
||||
## NPU
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
rm -rf core.*
|
||||
|
||||
source /usr/local/Ascend/ascend-toolkit/set_env.sh
|
||||
source /usr/local/Ascend/nnal/atb/set_env.sh
|
||||
export ASCEND_RT_VISIBLE_DEVICES=0
|
||||
export HCCL_IF_BASE_PORT=43432 # HCCL communication base port
|
||||
|
||||
|
||||
MODEL_PATH="/path/to/model/Qwen3-8B" # Model path
|
||||
MASTER_NODE_ADDR="127.0.0.1:9748" # Master node address (must be globally consistent)
|
||||
START_PORT=18000 # Service starting port
|
||||
START_DEVICE=0 # Starting logical device number
|
||||
LOG_DIR="log" # Log directory
|
||||
NNODES=1 # Number of nodes (current script launches 1 process)
|
||||
|
||||
mkdir -p $LOG_DIR
|
||||
|
||||
for (( i=0; i<$NNODES; i++ ))
|
||||
do
|
||||
PORT=$((START_PORT + i))
|
||||
DEVICE=$((START_DEVICE + i))
|
||||
LOG_FILE="$LOG_DIR/node_$i.log"
|
||||
/path/to/xllm \
|
||||
--model $MODEL_PATH \
|
||||
--devices="npu:$DEVICE" \
|
||||
--port $PORT \
|
||||
--master_node_addr=$MASTER_NODE_ADDR \
|
||||
--nnodes=$NNODES \
|
||||
--max_memory_utilization=0.86 \
|
||||
--block_size=128 \
|
||||
--communication_backend="hccl" \
|
||||
--enable_prefix_cache=false \
|
||||
--enable_chunked_prefill=true \
|
||||
--enable_schedule_overlap=true \
|
||||
--enable_shm=true \
|
||||
--node_rank=$i \ > $LOG_FILE 2>&1 &
|
||||
done
|
||||
```
|
||||
|
||||
## NVIDIA GPU
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
rm -rf core.*
|
||||
|
||||
export CUDA_VISIBLE_DEVICES=0
|
||||
# for debug
|
||||
# export CUDA_LAUNCH_BLOCKING=1
|
||||
|
||||
MODEL_PATH="/path/to/model/Qwen3-8B"
|
||||
MASTER_NODE_ADDR="127.0.0.1:9748"
|
||||
START_PORT=18000
|
||||
START_DEVICE=0
|
||||
LOG_DIR="log"
|
||||
NNODES=1
|
||||
|
||||
mkdir -p $LOG_DIR
|
||||
|
||||
for (( i=0; i<$NNODES; i++ ))
|
||||
do
|
||||
PORT=$((START_PORT + i))
|
||||
DEVICE=$((START_DEVICE + i))
|
||||
LOG_FILE="$LOG_DIR/node_$i.log"
|
||||
/path/to/xllm \
|
||||
--model $MODEL_PATH \
|
||||
--devices="cuda:$DEVICE" \
|
||||
--port $PORT \
|
||||
--master_node_addr=$MASTER_NODE_ADDR \
|
||||
--nnodes=$NNODES \
|
||||
--block_size=32 \
|
||||
--max_memory_utilization=0.8 \
|
||||
--enable_prefix_cache=false \
|
||||
--enable_chunked_prefill=false \
|
||||
--enable_schedule_overlap=true \
|
||||
--node_rank=$i \ > $LOG_FILE 2>&1 &
|
||||
done
|
||||
```
|
||||
|
||||
|
||||
## MLU
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
rm -rf core.*
|
||||
|
||||
export MLU_VISIBLE_DEVICES=0
|
||||
|
||||
MODEL_PATH="/path/to/model/Qwen3-8B"
|
||||
MASTER_NODE_ADDR="127.0.0.1:9748"
|
||||
START_PORT=18000
|
||||
START_DEVICE=0
|
||||
LOG_DIR="log"
|
||||
NNODES=1
|
||||
|
||||
mkdir -p $LOG_DIR
|
||||
|
||||
for (( i=0; i<$NNODES; i++ ))
|
||||
do
|
||||
PORT=$((START_PORT + i))
|
||||
DEVICE=$((START_DEVICE + i))
|
||||
LOG_FILE="$LOG_DIR/node_$i.log"
|
||||
/path/to/xllm \
|
||||
--model $MODEL_PATH \
|
||||
--devices="mlu:$DEVICE" \
|
||||
--port $PORT \
|
||||
--nnodes=$NNODES \
|
||||
--master_node_addr=$MASTER_NODE_ADDR \
|
||||
--block_size=16 \
|
||||
--node_rank=$i \ > $LOG_FILE 2>&1 &
|
||||
done
|
||||
```
|
||||
109
upstream_ref/xllm/docs/en/getting_started/multi_machine.md
Normal file
109
upstream_ref/xllm/docs/en/getting_started/multi_machine.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# Multi-Node Deployment
|
||||
This example demonstrates how to launch a 32-GPU (NPU) deployment across 2 machines.
|
||||
Launching Services on the First Machine:
|
||||
```shell
|
||||
bash start_deepseek_machine_1.sh
|
||||
```
|
||||
|
||||
The start_deepseek_machine_1.sh script is as follows:
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
rm -rf core.*
|
||||
|
||||
source /usr/local/Ascend/ascend-toolkit/set_env.sh
|
||||
source /usr/local/Ascend/nnal/atb/set_env.sh
|
||||
export HCCL_IF_BASE_PORT=43432 # HCCL communication base port
|
||||
|
||||
|
||||
# 4. Start distributed service
|
||||
MODEL_PATH="/path/to/your/DeepSeek-R1" # Model path
|
||||
MASTER_NODE_ADDR="123.123.123.123:9748" # Master node address (must be globally consistent)
|
||||
LOCAL_HOST=123.123.123.123 # Local IP for service launch
|
||||
START_PORT=18000 # Service starting port
|
||||
START_DEVICE=0 # Starting NPU logical device number
|
||||
LOCAL_NODES=16 # Number of local processes (this script launches 16 processes)
|
||||
LOG_DIR="log" # Log directory
|
||||
NNODES=32 # Total number of GPUs/NPUs (32 in this 2-machine example)
|
||||
|
||||
mkdir -p $LOG_DIR
|
||||
|
||||
for (( i=0; i<$LOCAL_NODES; i++ ))
|
||||
do
|
||||
PORT=$((START_PORT + i))
|
||||
DEVICE=$((START_DEVICE + i))
|
||||
LOG_FILE="$LOG_DIR/node_$i.log"
|
||||
/path/to/xllm \
|
||||
--model $MODEL_PATH \
|
||||
--host $LOCAL_HOST \
|
||||
--port $PORT \
|
||||
--devices="npu:$DEVICE" \
|
||||
--master_node_addr=$MASTER_NODE_ADDR \
|
||||
--nnodes=$NNODES \
|
||||
--max_memory_utilization=0.86 \
|
||||
--max_tokens_per_batch=40000 \
|
||||
--max_seqs_per_batch=256 \
|
||||
--block_size=128 \
|
||||
--enable_prefix_cache=false \
|
||||
--enable_chunked_prefill=false \
|
||||
--communication_backend="hccl" \
|
||||
--enable_schedule_overlap=true \
|
||||
--rank_tablefile=./ranktable_2s_32p.json \
|
||||
--node_rank=$i \ > $LOG_FILE 2>&1 &
|
||||
done
|
||||
```
|
||||
|
||||
Launching Services on the Second Machine:
|
||||
```shell
|
||||
bash start_deepseek_machine_2.sh
|
||||
```
|
||||
|
||||
The start_deepseek_machine_2.sh script is as follows:
|
||||
```bash
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
rm -rf core.*
|
||||
|
||||
source /usr/local/Ascend/ascend-toolkit/set_env.sh
|
||||
source /usr/local/Ascend/nnal/atb/set_env.sh
|
||||
export HCCL_IF_BASE_PORT=43432 # HCCL communication base port
|
||||
|
||||
MODEL_PATH="/path/to/your/DeepSeek-R1" # Model path
|
||||
MASTER_NODE_ADDR="123.123.123.123:9748" # Master node address (must be globally consistent)
|
||||
LOCAL_HOST=456.456.456.456 # Local IP for service launch
|
||||
START_PORT=18000 # Service starting port
|
||||
START_DEVICE=0 # Starting NPU logical device number
|
||||
LOCAL_NODES=16 # Number of local processes (this script launches 16 processes)
|
||||
LOG_DIR="log" # Log directory
|
||||
NNODES=32 # Total number of GPUs/NPUs (32 in this 2-machine example)
|
||||
|
||||
mkdir -p $LOG_DIR
|
||||
|
||||
for (( i=0; i<$LOCAL_NODES; i++ ))
|
||||
do
|
||||
PORT=$((START_PORT + i))
|
||||
DEVICE=$((START_DEVICE + i))
|
||||
LOG_FILE="$LOG_DIR/node_$i.log"
|
||||
/path/to/xllm \
|
||||
--model $MODEL_PATH \
|
||||
--host $LOCAL_HOST \
|
||||
--port $PORT \
|
||||
--devices="npu:$DEVICE" \
|
||||
--master_node_addr=$MASTER_NODE_ADDR \
|
||||
--nnodes=$NNODES \
|
||||
--max_memory_utilization=0.86 \
|
||||
--max_tokens_per_batch=40000 \
|
||||
--max_seqs_per_batch=256 \
|
||||
--block_size=128 \
|
||||
--enable_prefix_cache=false \
|
||||
--enable_chunked_prefill=false \
|
||||
--communication_backend="hccl" \
|
||||
--enable_schedule_overlap=true \
|
||||
--rank_tablefile=./ranktable_2s_32p.json \
|
||||
--node_rank=$((i + LOCAL_NODES)) \ > $LOG_FILE 2>&1 &
|
||||
done
|
||||
```
|
||||
This example uses 2 machines. You can set the total number of GPUs/NPUs via `--nnodes`, where `--node_rank` specifies the global rank ID for each node.
|
||||
The `--rank_tablefile=./ranktable_2s_32p.json`parameter points to the configuration file required for establishing the NPU communication domain. For instructions on generating this file, refer to [Ranktable Generation](https://gitee.com/mindspore/models/blob/master/utils/hccl_tools/README.md).
|
||||
15
upstream_ref/xllm/docs/en/getting_started/offline_service.md
Normal file
15
upstream_ref/xllm/docs/en/getting_started/offline_service.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# Offline Inference
|
||||
|
||||
To facilitate users in quickly using xLLM for offline inference, we provide Python script examples for launching offline inference.
|
||||
|
||||
## LLM
|
||||
|
||||
LLM inference example: [:simple-github: https://github.com/jd-opensource/xllm/blob/main/examples/generate.py](https://github.com/jd-opensource/xllm/blob/main/examples/generate.py)
|
||||
|
||||
## Embedding
|
||||
|
||||
Generate embedding example: [:simple-github: https://github.com/jd-opensource/xllm/blob/main/examples/generate_embedding.py](https://github.com/jd-opensource/xllm/blob/main/examples/generate_embedding.py)
|
||||
|
||||
## VLM
|
||||
|
||||
VLM inference example: [:simple-github: https://github.com/jd-opensource/xllm/blob/main/examples/generate_vlm.py](https://github.com/jd-opensource/xllm/blob/main/examples/generate_vlm.py)
|
||||
225
upstream_ref/xllm/docs/en/getting_started/online_service.md
Normal file
225
upstream_ref/xllm/docs/en/getting_started/online_service.md
Normal file
@@ -0,0 +1,225 @@
|
||||
# Online Service
|
||||
|
||||
First, start the xllm service according to the [xllm launch documentation](launch_xllm.md). Below are examples of client calls for LLM and VLM. Please modify the parameters according to your actual situation.
|
||||
|
||||
## LLM Client Calls
|
||||
### HTTP Call
|
||||
|
||||
Chat mode:
|
||||
```bash
|
||||
curl http://localhost:9977/v1/chat/completions \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "Qwen2-7B-Instruct",
|
||||
"max_tokens": 10,
|
||||
"temperature": 0,
|
||||
"stream": true,
|
||||
"messages": [
|
||||
{
|
||||
"role": "system",
|
||||
"content": "You are a helpful assistant."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "hello xllm"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
Completions mode:
|
||||
```bash
|
||||
curl http://127.0.0.1:9977/v1/completions \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "Qwen2-7B-Instruct",
|
||||
"prompt": "hello xllm",
|
||||
"max_tokens": 10,
|
||||
"temperature": 0,
|
||||
"stream": true
|
||||
}'
|
||||
```
|
||||
|
||||
Sample mode:
|
||||
```bash
|
||||
curl http://127.0.0.1:9977/v1/sample \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"model": "Qwen2-7B-Instruct",
|
||||
"prompt": "Question: <emb_0> matched or not. Conclusion: <emb_0>",
|
||||
"selector": {
|
||||
"type": "literal",
|
||||
"value": "<emb_0>"
|
||||
},
|
||||
"logprobs": 5,
|
||||
"request_id": "sample-demo-001"
|
||||
}'
|
||||
```
|
||||
|
||||
Typical response:
|
||||
```json
|
||||
{
|
||||
"id": "sample-demo-001",
|
||||
"object": "sample_completion",
|
||||
"created": 1773369600,
|
||||
"model": "Qwen2-7B-Instruct",
|
||||
"choices": [
|
||||
{
|
||||
"index": 0,
|
||||
"text": "True",
|
||||
"logprobs": {
|
||||
"tokens": ["True", "False"],
|
||||
"token_ids": [3456, 7890],
|
||||
"token_logprobs": [-0.12, -2.31]
|
||||
},
|
||||
"finish_reason": "selector_match"
|
||||
},
|
||||
{
|
||||
"index": 1,
|
||||
"text": "",
|
||||
"logprobs": {
|
||||
"tokens": [],
|
||||
"token_ids": [],
|
||||
"token_logprobs": []
|
||||
},
|
||||
"finish_reason": "empty_logprobs"
|
||||
}
|
||||
],
|
||||
"usage": {
|
||||
"prompt_tokens": 20,
|
||||
"completion_tokens": 2,
|
||||
"total_tokens": 22
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`/v1/sample` notes:
|
||||
|
||||
- Only `--backend=llm` is supported. VLM/DiT/Rec are not supported yet.
|
||||
- `selector.type` is currently fixed to `literal`. `selector.value` is matched against prompt text in full and in order.
|
||||
- `logprobs` defaults to `5`, with an allowed range of `[1, 5]`.
|
||||
- `choices[i].index` is the matched `sample_id`, corresponding one-to-one with the matched order in prompt.
|
||||
- If no selector match is found, the service returns `200` with `choices=[]`. If a matched position has no available logprobs, it returns `finish_reason="empty_logprobs"`.
|
||||
- Service logs only summary fields such as `request_id`, `sample_id`, `match_count`, and `model`, and do not log the full prompt.
|
||||
|
||||
`/v1/sample` common error semantics:
|
||||
|
||||
- Missing `model/prompt/selector/selector.value`, `selector.type != literal`, or out-of-range `logprobs` returns `INVALID_ARGUMENT`.
|
||||
- If the model does not exist or the backend is not `llm`, it returns `UNKNOWN`.
|
||||
- When concurrency reaches the upper limit, it returns `RESOURCE_EXHAUSTED`.
|
||||
- When the model is in sleep state, it returns `UNAVAILABLE`.
|
||||
|
||||
### Python Call
|
||||
```python
|
||||
import requests
|
||||
import json
|
||||
|
||||
url = f"http://localhost:9977/v1/chat/completions"
|
||||
messages = [
|
||||
{'role': 'user', 'content': "List three countries and their capitals."}
|
||||
]
|
||||
|
||||
request_data = {
|
||||
"model": "Qwen2-7B-Instruct",
|
||||
"messages": messages,
|
||||
"stream": False,
|
||||
"temperature": 0.6,
|
||||
"max_tokens": 2048,
|
||||
}
|
||||
|
||||
response = requests.post(url, json=request_data)
|
||||
if response.status_code != 200:
|
||||
print(response.status_code, response.text)
|
||||
else:
|
||||
ans = json.loads(response.text)["choices"]
|
||||
print(ans[0]['message'])
|
||||
```
|
||||
|
||||
|
||||
## VLM Client Calls
|
||||
### HTTP API
|
||||
|
||||
```python
|
||||
import base64
|
||||
import requests
|
||||
|
||||
api_url = "http://localhost:12345/v1/chat/completions"
|
||||
image_url = ""
|
||||
|
||||
def encode_image(url: str) -> str:
|
||||
with requests.get(url) as response:
|
||||
response.raise_for_status()
|
||||
result = base64.b64encode(response.content).decode("utf-8")
|
||||
|
||||
return result
|
||||
|
||||
image_base64 = encode_image(image_url)
|
||||
payload = {
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "Describe this image"},
|
||||
{
|
||||
"type": "image_url",
|
||||
"image_url": {"url": f"data:image/jpeg;base64,{image_base64}"},
|
||||
},
|
||||
],
|
||||
}
|
||||
],
|
||||
"model": "Qwen2.5-VL-7B-Instruct",
|
||||
"max_completion_tokens": 128,
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
api_url,
|
||||
json=payload,
|
||||
headers={"Content-Type": "application/json"}
|
||||
)
|
||||
print(response.json())
|
||||
```
|
||||
|
||||
|
||||
### OpenAI API
|
||||
```python
|
||||
from openai import OpenAI
|
||||
import base64
|
||||
import requests
|
||||
|
||||
openai_api_key = "EMPTY"
|
||||
openai_api_base = "http://localhost:12345/v1"
|
||||
image_url = ""
|
||||
|
||||
client = OpenAI(
|
||||
api_key=openai_api_key,
|
||||
base_url=openai_api_base,
|
||||
)
|
||||
|
||||
def encode_image(url: str) -> str:
|
||||
with requests.get(url) as response:
|
||||
response.raise_for_status()
|
||||
result = base64.b64encode(response.content).decode("utf-8")
|
||||
|
||||
return result
|
||||
|
||||
image_base64 = encode_image(image_url)
|
||||
chat_completion = client.chat.completions.create(
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "Describe this image"},
|
||||
{
|
||||
"type": "image_url",
|
||||
"image_url": {"url": f"data:image/jpeg;base64,{image_base64}"},
|
||||
},
|
||||
],
|
||||
}
|
||||
],
|
||||
model="Qwen2.5-VL-7B-Instruct",
|
||||
max_completion_tokens=128,
|
||||
)
|
||||
|
||||
result = chat_completion.choices[0].message.content
|
||||
print("Chat completion output:", result)
|
||||
```
|
||||
107
upstream_ref/xllm/docs/en/getting_started/quick_start.md
Normal file
107
upstream_ref/xllm/docs/en/getting_started/quick_start.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Quick Start
|
||||
|
||||
## Environment Setup
|
||||
|
||||
All images are stored [here](https://quay.io/repository/jd_xllm/xllm-ai?tab=tags). The docker startup command below uses the dev image as an example.
|
||||
|
||||
### NPU
|
||||
|
||||
Below are our pre-built dev image.
|
||||
```bash
|
||||
# A2 x86
|
||||
docker pull quay.io/jd_xllm/xllm-ai:xllm-dev-a2-x86-20260429
|
||||
# A2 arm
|
||||
docker pull quay.io/jd_xllm/xllm-ai:xllm-dev-a2-arm-20260429
|
||||
# A3 arm
|
||||
docker pull quay.io/jd_xllm/xllm-ai:xllm-dev-a3-arm-20260429
|
||||
```
|
||||
|
||||
Container startup command:
|
||||
```bash
|
||||
docker run -it \
|
||||
--ipc=host \
|
||||
-u 0 \
|
||||
--name xllm-npu \
|
||||
--privileged \
|
||||
--network=host \
|
||||
--device=/dev/davinci0 \
|
||||
--device=/dev/davinci_manager \
|
||||
--device=/dev/devmm_svm \
|
||||
--device=/dev/hisi_hdc \
|
||||
-v /usr/local/Ascend/driver:/usr/local/Ascend/driver \
|
||||
-v /usr/local/Ascend/add-ons/:/usr/local/Ascend/add-ons/ \
|
||||
-v /usr/local/sbin/npu-smi:/usr/local/sbin/npu-smi \
|
||||
-v /usr/local/sbin/:/usr/local/sbin/ \
|
||||
-v /var/log/npu/conf/slog/slog.conf:/var/log/npu/conf/slog/slog.conf \
|
||||
-v /var/log/npu/slog/:/var/log/npu/slog \
|
||||
-v /var/log/npu/profiling/:/var/log/npu/profiling \
|
||||
-v /var/log/npu/dump/:/var/log/npu/dump \
|
||||
-v $HOME:$HOME \
|
||||
-w $HOME \
|
||||
<docker_image_name> \
|
||||
/bin/bash
|
||||
```
|
||||
|
||||
### NVIDIA GPU
|
||||
|
||||
We provide a [Dockerfile](../../../docker/Dockerfile.cuda) for NVIDIA GPU usage, which can be used to build custom image. Of course, you can also use dev image we built based on the default Dockerfile:
|
||||
```bash
|
||||
docker pull quay.io/jd_xllm/xllm-ai:xllm-dev-cuda-x86
|
||||
```
|
||||
|
||||
Container startup command:
|
||||
```bash
|
||||
sudo docker run -it \
|
||||
--privileged \
|
||||
--shm-size '128gb' \
|
||||
--ipc=host \
|
||||
--net=host \
|
||||
--pid=host \
|
||||
--name=xllm-cuda \
|
||||
-v $HOME:$HOME \
|
||||
-w $HOME \
|
||||
<docker_image_name> \
|
||||
/bin/bash
|
||||
```
|
||||
|
||||
### MLU
|
||||
|
||||
We cannot provide MLU image. If you already have the dev image, you can start the container with the following command:
|
||||
```bash
|
||||
sudo docker run -it \
|
||||
--privileged \
|
||||
--shm-size '128gb' \
|
||||
--ipc=host \
|
||||
--net=host \
|
||||
--pid=host \
|
||||
--name xllm-mlu \
|
||||
-v $HOME:$HOME \
|
||||
-w $HOME \
|
||||
<docker_image_name> \
|
||||
/bin/bash
|
||||
```
|
||||
|
||||
## Build xllm
|
||||
|
||||
If you download a release image, i.e., an image with a version number in the tag, you can skip this step because the release image comes with a pre-compiled xllm binary, located at `/usr/local/bin/xllm`.
|
||||
|
||||
Download xllm and dependencies:
|
||||
```bash
|
||||
git clone https://github.com/jd-opensource/xllm
|
||||
cd xllm
|
||||
|
||||
# Install pre-commit for the first time
|
||||
pip install pre-commit
|
||||
pre-commit install
|
||||
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
The compiled binary file is located at `/path/to/xllm/build/xllm/core/server/xllm`. In a new image, the first compilation of xllm takes a long time because all dependencies in vcpkg need to be compiled, but subsequent compilations will be much faster.
|
||||
```bash
|
||||
python setup.py build
|
||||
```
|
||||
|
||||
## Launch xllm
|
||||
Please refer to [How to Launch xllm](launch_xllm.md).
|
||||
|
||||
Reference in New Issue
Block a user