How to Build a RAG Pipeline With Qwen on Alibaba Cloud
Most retrieval augmented generation tutorials make you stitch together three vendors before you've written a line of business logic. On Alibaba Cloud you don't have to: Model Studio embeds and generates with Qwen, and AnalyticDB for PostgreSQL stores the vectors next to your relational data. This walkthrough builds a Qwen RAG Alibaba Cloud pipeline end to end, no external vector database required, using Qwen3's text-embedding-v4 for embeddings and Qwen for the final answer.
By the end you'll have documents chunked, embedded, stored in an AnalyticDB vector column with a proper index, and queried at request time to ground a Qwen response.
Set up Alibaba Cloud Model Studio and AnalyticDB
Create a workspace in Alibaba Cloud Model Studio and grab an API key from the console. Model Studio is the front end for DashScope, which serves both the embedding and chat models you'll use below.
Separately, provision an AnalyticDB for PostgreSQL instance (version 7.0 or later ships with the ANN vector index built in). Export your credentials so the rest of the pipeline can pick them up:
export DASHSCOPE_API_KEY="<your-dashscope-api-key>"
export ADBPG_HOST="<your-instance>.gpdb.rds.aliyuncs.com"
export ADBPG_DB="ragdemo"
export ADBPG_USER="<your-db-user>"
export ADBPG_PASSWORD="<your-db-password>"
Create a vector table in AnalyticDB
AnalyticDB for PostgreSQL is wire-compatible with Postgres, so any client that speaks psycopg2 works. Connect with psql (or a script) and create a table with a real[] column for the embedding, plus an ANN index over it:
CREATE TABLE doc_chunks (
id serial PRIMARY KEY,
doc_name text,
chunk text,
embedding real[]
) DISTRIBUTED BY (id);
CREATE INDEX idx_doc_chunks_embedding
ON doc_chunks USING ann(embedding)
WITH (dim=1024, distancemeasure=cosine, hnsw_m=64, hnsw_ef_construction=128, pq_enable=0);
DISTRIBUTED BY is required because AnalyticDB shards data across nodes. dim=1024 matches the default output size of text-embedding-v4; keep the two in sync or your inserts will fail silently on dimension mismatch.
Embed your documents with Qwen3's text-embedding-v4
Model Studio exposes an OpenAI-compatible endpoint, so the standard openai Python package works with no custom SDK. Chunk your documents (a simple paragraph or fixed-token splitter is fine to start), then embed them in batches, since text-embedding-v4 caps requests at 10 inputs and 8,192 tokens each:
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["DASHSCOPE_API_KEY"],
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
def embed_batch(texts):
resp = client.embeddings.create(
model="text-embedding-v4",
input=texts,
dimensions=1024,
encoding_format="float",
)
return [d.embedding for d in resp.data]
chunks = ["...", "..."] # your chunked document text
vectors = []
for i in range(0, len(chunks), 10):
vectors.extend(embed_batch(chunks[i:i + 10]))
Load vectors into AnalyticDB
Insert each chunk and its vector with psycopg2. AnalyticDB's real[] column accepts a plain Python list, no special adapter needed:
import psycopg2
conn = psycopg2.connect(
host=os.environ["ADBPG_HOST"], dbname=os.environ["ADBPG_DB"],
user=os.environ["ADBPG_USER"], password=os.environ["ADBPG_PASSWORD"], port=5432,
)
cur = conn.cursor()
for chunk_text, vec in zip(chunks, vectors):
cur.execute(
"INSERT INTO doc_chunks (doc_name, chunk, embedding) VALUES (%s, %s, %s)",
("handbook.pdf", chunk_text, vec),
)
conn.commit()
Retrieve chunks with vector search
At query time, embed the user's question with the same model and dimension, then let AnalyticDB's ANN index do the ranking. The <=> operator matches the cosine distance measure set on the index:
question = "What's our refund policy for enterprise contracts?"
q_vector = embed_batch([question])[0]
cur.execute(
"SELECT chunk FROM doc_chunks ORDER BY embedding <=> %s::real[] LIMIT 5",
(q_vector,),
)
context = "\n\n".join(row[0] for row in cur.fetchall())
Generate the answer with Qwen
Feed the retrieved chunks back into a Qwen chat call as context. qwen-plus is the balanced tier Alibaba recommends for most production RAG workloads:
completion = client.chat.completions.create(
model="qwen-plus",
messages=[
{"role": "system", "content": "Answer only using the provided context. If the context doesn't cover it, say so."},
{"role": "user", "content": f"Context:\n{context}\n\nQuestion: {question}"},
],
)
print(completion.choices[0].message.content)
Gotchas
- Batch limits are real.
text-embedding-v4rejects requests over 10 inputs or 8,192 tokens per input; a silent truncation is worse than an error, so batch explicitly. - Dimension drift breaks retrieval, not inserts. If you change
dimensionsin your embedding call without rebuilding the index, results just get worse, they don't error out. Rebuild the index after any dimension change. - Match the distance operator to the index.
<=>for cosine and<->for Euclidean aren't interchangeable; using the wrong one still runs, it just ignores your index and falls back to a sequential scan. - Region availability varies.
text-embedding-v4is available in Beijing, Hong Kong, and Singapore regions; confirm your AnalyticDB instance and Model Studio workspace are in a region where both the embedding and chat models you want are actually served.
Get these five pieces talking to each other once, and you've got a retrieval augmented generation pipeline that lives entirely inside Alibaba Cloud's billing and IAM boundary, which is one less cross-cloud integration to secure and debug when this moves from pilot to production.