使用说明
MCP本地LLM服务器
A. FastMCP 公开本地托管的服务器 llama.cpp 语言模型作为MCP工具,以及一套用于天气、新闻、网络获取、文件I/O、股票数据、摘要等的实用工具。
概述
该服务器允许任何兼容MCP的客户端(例如Claude Desktop、Cursor)使用本地GGUF模型进行文本生成和聊天,而无需向外部API发送数据。该模型由一个 llama-server 子流程;MCP服务器通过本地HTTP端口与其通信。
src/
├── llm_server.py # Entry point, argument parsing, server startup
├── model.py # llama-server lifecycle, token generation
├── upload.py # POST /upload endpoint for PDF and Markdown file uploads
├── resources.py # MCP resource: llm://info
└── tools/
├── generate.py # Tool: generate
├── chat.py # Tool: chat
├── weather.py # Tool: get_weather
├── date_time.py # Tool: get_datetime
├── fetch_url.py # Tool: fetch_url
├── news.py # Tool: news_headlines
├── read_pdf.py # Tool: read_pdf
├── read_markdown.py # Tool: read_markdown
├── create_file.py # Tool: create_file
├── list_directory.py# Tool: list_directory
├── stock_price.py # Tool: get_stock_price
├── summarize.py # Tool: summarize_text
├── agent.py # Tool: run_agent (autonomous ReAct agent)
├── explain_code.py # Tool: explain_code (coding tutor)
├── review_code.py # Tool: review_code (coding tutor)
├── coding_tutor.py # Tool: coding_tutor (orchestrating tutor agent)
├── transcribe_audio.py # Tool: transcribe_audio
├── text_to_speech.py # Tool: text_to_speech
├── word_definition.py # Tool: define_word
└── random_joke.py # Tool: get_random_joke
需求
- Python 3.10+
- A.
llama-server二进制从 llama.cpp - GGUF模型文件(例如。
models/Qwen2.5-7B-Instruct-Q4_K_M.gguf) - 支持CUDA的GPU推荐用于大型型号
安装依赖项:
pip install -r requirements.txt
在Windows上,IANA时区数据不与Python捆绑在一起。安装它 get_datetime 支持非UTC时区的工具:
pip install tzdata
这 transcribe_audio 工具需要 faster-whisper,如所列 requirements.txt 但具有可选的CUDA加速变体。对于GPU推理,请先安装匹配的PyTorch CUDA版本:
# CPU-only (default)
pip install faster-whisper
# GPU (CUDA 12)
pip install faster-whisper
pip install torch --index-url https://download.pytorch.org/whl/cu128
配置
某些工具需要API密钥。创建一个 .env 项目根目录中的文件(已被gitignored):
NEWSAPI_KEY=your_key_here
服务器在启动时自动加载此文件。
| 变量 | 必填 | 从哪里获取 |
|---|---|---|
NEWSAPI_KEY |
news_headlines |
newsapi.org --免费套餐可用 |
所有其他工具都可以在没有任何API密钥的情况下工作。
启动服务器
stdio传输(适用于Claude Desktop等MCP客户端)
python src/llm_server.py \
--model models/Qwen2.5-7B-Instruct-Q4_K_M.gguf \
--llama-server /path/to/llama-server
HTTP传输(用于网络客户端或使用curl进行测试)
python src/llm_server.py \
--model models/Qwen2.5-7B-Instruct-Q4_K_M.gguf \
--llama-server /path/to/llama-server \
--transport http \
--port 5174
CLI标志
| 标志 | 默认值 | 描述 |
|---|---|---|
--model |
(必填) | 通往a的道路 .gguf 文件或包含一个文件的目录 |
--llama-server |
(必填) | 通往 llama-server 可执行文件 |
--transport |
stdio |
stdio 或 http |
--host |
0.0.0.0 |
要绑定HTTP传输的主机(使用 127.0.0.1 仅适用于本地主机) |
--port |
5174 |
MCP服务器端口(仅限HTTP传输) |
--server-port |
8080 |
内部llama服务器后端的端口 |
--gpu-layers |
-1 |
要卸载到GPU的层; -1 =全部 |
--context-size |
16384 |
令牌中的总上下文窗口(提示+输出组合) |
HTTP端点
这些端点仅在使用时可用 --transport http.
POST /upload
将PDF或Markdown文件上传到服务器并接收 upload_id 传递给 run_agent.
支持的类型: .pdf, .md, .markdown
请求: multipart/form-data 有一个名为的字段 file.
答复:
{
"upload_id": "3f8a1c...",
"filename": "report.pdf",
"size": 84210
}
上传的文件存储在 uploads/ 在项目根目录下,并在服务器关闭时删除。
例子:
curl -X POST http://localhost:5174/upload \
-F "file=@/path/to/report.pdf"
curl -X POST http://localhost:5174/upload \
-F "file=@/path/to/notes.md"
工具
generate
从原始提示生成文本。输入提示为 不 包含在返回的文本中。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
prompt |
string |
(必填) | 输入文本以继续 |
max_new_tokens |
int |
512 |
要生成的最大令牌数 |
temperature |
float |
0.7 |
取样温度; 0 =贪婪(确定性) |
top_p |
float |
0.9 |
核采样累积概率截止值 |
top_k |
int |
0 |
Top-k词汇过滤器; 0 =已禁用 |
repetition_penalty |
float |
1.0 |
重复代币的处罚; 1.0 =无罚金 |
stop_sequences |
list[string] |
null |
生成时停止生成的字符串 |
seed |
int |
null |
用于可重复输出的RNG种子 |
退货: 以纯字符串形式生成的文本。
示例
{
"prompt": "The capital of France is",
"max_new_tokens": 50,
"temperature": 0
}
chat
使用对话历史记录与当地LLM聊天。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
messages |
list[{"role": string, "content": string}] |
(必填) | 对话历史。有效角色: "system", "user", "assistant" |
max_new_tokens |
int |
512 |
要生成的最大令牌数 |
temperature |
float |
0.7 |
取样温度; 0 =贪婪(确定性) |
top_p |
float |
0.9 |
核采样累积概率截止值 |
top_k |
int |
0 |
Top-k词汇过滤器; 0 =已禁用 |
repetition_penalty |
float |
1.0 |
重复代币的处罚; 1.0 =无罚金 |
stop_sequences |
list[string] |
null |
生成时停止生成的字符串 |
seed |
int |
null |
用于可重复输出的RNG种子 |
退货: 助理的回答是纯文本的。
示例
{
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What is the Eiffel Tower?"}
],
"temperature": 0.7,
"max_new_tokens": 256
}
get_weather
使用免费获取任何位置的当前天气 开放气象API。不需要API密钥。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
location |
string |
(必填) | 城市名称或地区(例如。 "London", "New York", "Tokyo") |
units |
string |
"metric" |
"metric" (°C,km/h)或 "imperial" (°F,mph) |
退货: 当前条件、温度、湿度和风速。
输出示例
Weather in London, England, United Kingdom:
Conditions: Partly cloudy
Temperature: 12.3°C
Humidity: 74%
Wind: 18.5 km/h
get_datetime
返回任何IANA时区的当前日期和时间。不需要API密钥。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
timezone |
string |
"UTC" |
IANA时区名称(例如。 "America/New_York", "Europe/London", "Asia/Tokyo") |
退货: 格式化的日期/时间字符串,例如。 "2025-03-01 14:30:00 EST (UTC-0500)".
Windows注意事项: 非UTC时区需要
pip install tzdata.
示例
{"timezone": "America/Chicago"}
fetch_url
获取任何URL的内容并以纯文本形式返回。HTML页面去掉了标签;JSON和纯文本响应以原样返回。不需要API密钥。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
url |
string |
(必填) | 要获取的URL(必须以开头 http:// 或 https://) |
max_chars |
int |
4000 |
截断前返回的最大字符数 |
退货: 提取的页面文本,截断为 max_chars 如果需要的话。连接失败时返回描述性错误字符串,而不是引发异常。
示例
{
"url": "https://en.wikipedia.org/wiki/Python_(programming_language)",
"max_chars": 2000
}
news_headlines
获取最新的新闻标题,可选择按主题过滤。需要免费 新闻API 钥匙。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
topic |
string |
"" |
要筛选的关键字(例如。 "AI", "climate change").一般头条新闻留空 |
country |
string |
"us" |
使用2个字母的国家代码 topic 为空白(例如。 us, gb, au, de) |
max_results |
int |
5 |
返回的标题数量(1-10) |
退货: 标题的编号列表,包括来源、发布日期和URL。
示例
{"topic": "artificial intelligence", "max_results": 3}
输出示例
1. [BBC News] OpenAI releases new model
Published: 2025-03-01
https://bbc.co.uk/...
2. [Reuters] ...
read_pdf
提取并返回按页面组织的PDF文件的文本内容。纯图像(扫描)PDF返回清晰的信息,而不是空输出。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
file_path |
string |
(必填) | PDF文件的绝对或相对路径 |
max_chars |
int |
8000 |
截断前返回的最大字符数 |
退货: 按页面组织的提取文本,截断为 max_chars 如果需要的话。
示例
{"file_path": "/home/user/documents/report.pdf", "max_chars": 10000}
read_markdown
读取并返回Markdown文件的内容。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
file_path |
string |
(必填) | 到的绝对或相对路径 .md 或 .markdown 文件 |
max_chars |
int |
8000 |
截断前返回的最大字符数 |
退货: 文件的文本内容,截断为 max_chars 如果需要的话。
示例
{"file_path": "/home/user/documents/notes.md"}
create_file
使用给定的名称和内容创建一个新文件。拒绝路径遍历尝试,并在写入之前验证文件名。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
file_name |
string |
(必填) | 要创建的文件的基本名称(不允许使用路径分隔符) |
content |
string |
(必填) | 要写入文件的文本内容 |
directory |
string |
null |
创建文件的子目录(相对于服务器的工作目录)。如果不存在则创建 |
encoding |
string |
"utf-8" |
文件的字符编码 |
overwrite |
bool |
false |
如果 true,覆盖同一路径上的现有文件 |
退货: 一个带有键的JSON对象:
success—true如果文件已创建file_path--创建文件的绝对路径(null失败)error--如果出现错误消息success是falsemessage--人类可读状态
示例
{"file_name": "notes.md", "content": "# My Notes\n"}
{
"file_name": "config.json",
"content": "{\"debug\": true}",
"directory": "src",
"overwrite": true
}
list_directory
列出给定路径下的文件和目录,并使用可选的glob过滤和递归遍历。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
path |
string |
(必填) | 要列出的目录的绝对或相对路径 |
pattern |
string |
"*" |
用于过滤结果的Glob模式(例如。 "*.py", "data_*", "**/*.json") |
recursive |
bool |
false |
如果 true,遍历所有子目录 |
include_hidden |
bool |
false |
如果 true,包括名称以开头的文件和文件夹 "." |
max_results |
int |
200 |
要返回的最大条目数 |
退货: 一个格式化的列表,显示 [DIR] 和 [FILE] 包含文件大小的条目,加上摘要计数。如果出现以下情况,则会注意到截断 max_results 已达到。
示例
{"path": "/home/user/projects"}
{
"path": "/home/user/projects/mcp-server",
"pattern": "*.py",
"recursive": true
}
输出示例
Directory: /home/user/projects/mcp-server/src
[DIR] tools/
[FILE] llm_server.py (4 KB)
[FILE] model.py (7 KB)
[FILE] resources.py (1 KB)
[FILE] upload.py (2 KB)
4 item(s) shown
get_stock_price
通过以下方式获取股票代码的当前股价和关键市场数据 雅虎财经API。不需要API密钥。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
ticker |
string |
(必填) | 股票代码(例如。 "AAPL", "MSFT", "TSLA", "BTC-USD") |
退货: 当前价格、每日变化、日范围、52周范围、交易量和市值。
示例
{"ticker": "NVDA"}
输出示例
NVIDIA Corp (NVDA)
Price: 875.40 USD
Change: +12.30 (+1.43%)
Prev close: 863.10 USD
Day range: 860.00 – 879.50 USD
52-wk range: 410.00 – 974.00 USD
Volume: 42,381,200
Market cap: 2.16T USD
提示: 还支持加密货币对(例如。
"BTC-USD","ETH-USD").
summarize_text
使用本地LLM总结一段文本。长文本会自动分成块,每个块都独立总结,然后合并成一个连贯的摘要。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
text |
string |
(必填) | 要总结的文本。可以任意长 |
focus |
string |
"" |
指导摘要的可选说明(例如。 "key risks", "action items", "technical details").一般摘要留空 |
max_length |
int |
200 |
摘要的大致最大长度(以令牌为单位)。控制冗长 |
退货: 输入文本的简明摘要。
示例
{"text": "... (long article) ..."}
{
"text": "... (meeting transcript) ...",
"focus": "action items",
"max_length": 150
}
{
"text": "... (technical document) ...",
"focus": "key risks",
"max_length": 300
}
transcribe_audio
使用本地将音频文件转录为文本 耳语 模型via 更快的耳语.完全在设备上运行-不需要API密钥或互联网连接。模型在首次使用时会自动下载并在本地缓存。
支持的格式: mp3、mp4、wav、flac、ogg、m4a、webm和大多数ffmpeg可读格式。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
audio_path |
string |
(必填) | 音频文件的绝对或相对路径 |
model_size |
string |
"base" |
要使用的Whisper型号: "tiny" (~150mb), "base" (~290mb), "small" (~970mb), "medium" (~3.1gb), "large-v3" (约6.2 GB) |
language |
string |
null |
ISO-639-1强制语言代码(例如。 "en", "fr").离开 null 自动检测 |
device |
string |
"auto" |
推理设备。 "auto" 选择CUDA(如果可用),否则选择CPU。明确的: "cuda", "cpu" |
compute_type |
string |
"auto" |
精度。 "auto" 用途 float16 GPU和 int8 在CPU上。明确的: "float16", "int8", "float32" |
退货: 一个带有键的JSON对象:
success—true如果转录成功text--转录文本(null失败)language--检测到的或强制的语言代码duration_seconds--音频持续时间(秒)error--如果出现错误消息success是false
示例
{"audio_path": "/home/user/recordings/meeting.mp3"}
{
"audio_path": "/home/user/recordings/lecture.wav",
"model_size": "small",
"language": "en"
}
提示: 使用
"tiny"或"base"用于快速转录短片。使用"small"或更高,以便在嘈杂的音频或非英语语音上获得更好的准确性。
run_agent
运行自主 交互式推理与行动 由本地LLM驱动的代理。代理逐步推理,并在产生最终答案之前根据需要多次调用工具。
运作原理
User goal
↓
LLM decides: call a tool or answer?
↓ (if tool)
Tool executes → result fed back to LLM
↓
LLM decides again … (repeats up to max_steps)
↓ (when done)
FINAL answer returned
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
goal |
string |
(必填) | 代理人要解决的任务或问题 |
max_steps |
int |
10 |
停止前工具调用的最大迭代次数 |
max_new_tokens |
int |
4096 |
每次LLM呼叫的令牌上限。主要影响最终答案的长度 |
max_history_pairs |
int |
4 |
最近助理+工具查房,保持完整;对旧回合进行了总结 |
summary_strategy |
string |
"deterministic" |
"deterministic" --基于规则的快速要点。 "llm" --模型生成的散文(添加额外的生成调用) |
upload_id |
string |
"" |
返回的ID POST /upload。在循环开始之前,文件的内容被注入到代理的上下文中 |
退货: 代理人的最终回答是纯文本。
如果你看到
Agent stopped after N steps without a FINAL answer,代理用尽了它的迭代。要么增加max_steps或者简化目标。
代理可用的工具
| 工具 | 说明 |
|---|---|
get_weather |
获取任何城市的当前天气 |
get_datetime |
获取任何时区的当前日期和时间 |
fetch_url |
从任何URL获取和提取文本 |
news_headlines |
按主题获取最新新闻头条 |
read_pdf |
从给定路径的PDF文件中提取文本 |
read_markdown |
读取给定路径下Markdown文件的内容 |
get_stock_price |
获取股票代码的当前股价和市场数据 |
summarize_text |
使用本地LLM总结一段文本 |
create_file |
使用给定的名称和内容创建新文件 |
list_directory |
列出给定路径下的文件和目录 |
transcribe_audio |
使用本地Whisper模型将音频文件转录为文本 |
示例
{"goal": "What should I wear in Paris today?"}
{"goal": "Compare the weather in London and Tokyo, then tell me which city is warmer."}
{"goal": "Summarise this document", "upload_id": "3f8a1c..."}
{
"goal": "What are the top AI news stories today?",
"max_steps": 5
}
text_to_speech
使用将文本转换为MP3音频文件 谷歌文本转语音(gTTS)。需要互联网连接。不需要API密钥。
附属国: 安装
gTTS在使用此工具之前:pip install gtts
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
text |
string |
(必填) | 要转换为语音的文本 |
output_path |
string |
(必填) | 保存MP3的文件路径(例如。 "output/speech.mp3").父目录是自动创建的 |
lang |
string |
"en" |
BCP-47语言代码(例如。 "en", "fr", "es", "de", "ja") |
slow |
bool |
false |
如果 true,语音生成速度较慢 |
退货: 一个带有键的JSON对象:
success—true如果文件保存成功output_path--保存的MP3的绝对路径(null失败)error--如果出现错误消息success是false
示例
{
"text": "Hello, world!",
"output_path": "output/hello.mp3"
}
{
"text": "Bonjour le monde",
"output_path": "output/bonjour.mp3",
"lang": "fr",
"slow": true
}
define_word
使用免费工具查找英语单词的定义、语音、同义词和反义词 词典API。不需要API密钥。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
word |
string |
(必填) | 要查找的英语单词(例如。 "ephemeral", "serendipity") |
退货: 一个带有键的JSON对象:
success—true如果找到了这个词word--查找到的正常化单词results--含义列表,每个含义包含:phonetic--IPA语音拼写(可能是null)part_of_speech--例如。"noun","verb","adjective"definitions--最多3个定义,每个定义definition,example(可能是null),synonyms(最多5个),antonyms(最多5个)synonyms--该词性最多5个同义词antonyms--这个词类最多有5个反义词
error--如果出现错误消息success是false
示例
{"word": "ephemeral"}
示例输出(缩写)
{
"success": true,
"word": "ephemeral",
"results": [
{
"phonetic": "/ɪˈfɛm(ə)r(ə)l/",
"part_of_speech": "adjective",
"definitions": [
{
"definition": "Lasting for a very short time.",
"example": "fashions are ephemeral",
"synonyms": ["transitory", "transient", "fleeting"],
"antonyms": ["permanent", "eternal"]
}
],
"synonyms": ["transitory", "transient"],
"antonyms": ["permanent"]
}
],
"error": null
}
get_random_joke
从免费网站上随机下载一个笑话 JokeAPI。不需要API密钥。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
category |
string |
"Any" |
笑话类别: "Any", "Programming", "Misc", "Dark", "Pun", "Spooky", "Christmas" |
joke_type |
string |
"any" |
格式筛选器: "any", "single" (一个衬垫), "twopart" (设置+打孔线) |
safe_mode |
bool |
true |
如果 true,不包括露骨、种族主义、性别歧视和宗教笑话 |
退货: 一个带有键的JSON对象:
success—true如果一个笑话被退回category--这个笑话属于哪一类type—"single"或"twopart"joke--笑话文本;由两部分组成的笑话格式如下"setup\n\n— delivery"error--如果出现错误消息success是false
注: 这
"Dark"类别在以下情况下不可用safe_mode是true.
示例
{"category": "Programming"}
{
"category": "Pun",
"joke_type": "twopart",
"safe_mode": true
}
编码导师工具
三种将服务器变成交互式编程导师的工具。高级入口点是 coding_tutor两个辅助工具(explain_code, review_code)也可以直接调用。
coding_tutor
自主的 交互式推理与行动 专门从事教学的代理人。它一步一步推理,调用 explain_code, review_code,以及 fetch_url 根据需要,然后产生教学响应。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
question |
string |
(必填) | 您的编码问题、代码片段或错误消息 |
max_steps |
int |
8 |
停止前工具调用的最大迭代次数 |
max_new_tokens |
int |
1024 |
每次LLM呼叫的令牌上限 |
max_history_pairs |
int |
4 |
在总结旧回合之前,应保留最近的助理+工具回合 |
summary_strategy |
string |
"deterministic" |
"deterministic" (快速)或 "llm" (散文,慢点) |
退货: 纯文本的教学回应。
导师可用的工具
| 工具 | 说明 |
|---|---|
explain_code |
根据学习者的技能水平解释代码片段 |
review_code |
检查代码中的错误、样式、安全性或性能问题 |
fetch_url |
获取学习者引用的文档或GitHub链接 |
示例
{"question": "Why does my list comprehension give the wrong result?\n\nresult = [x * 2 for x in [1, 2, 3] if x > 1]"}
{"question": "Explain the difference between a shallow copy and a deep copy in Python, with examples."}
提示: 导师从你的问题中推断出你的技能水平——初级解释使用简单的语言,高级解释使用技术术语。
explain_code
根据学习者的技能水平,使用本地LLM解释代码片段。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
code |
string |
(必填) | 要解释的源代码(最多6000个字符) |
language |
string |
"python" |
代码段的编程语言 |
level |
string |
"beginner" |
解释深度: "beginner", "intermediate",或 "advanced" |
max_new_tokens |
int |
1024 |
解释的最大令牌数 |
退货: 代码的纯文本解释。
示例
{
"code": "result = {k: v for k, v in zip(keys, values)}",
"language": "python",
"level": "beginner"
}
review_code
检查代码片段是否存在问题。输出一份结构化的报告:总体印象、严重性编号的问题、积极因素和最高建议。
参数
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
code |
string |
(必填) | 要查看的源代码(最多6000个字符) |
language |
string |
"python" |
代码段的编程语言 |
focus |
string |
"general" |
评审重点: "general", "security", "performance",或 "style" |
max_new_tokens |
int |
768 |
评论的最大令牌数 |
退货: 分为四个部分的结构化审查: 总体印象, 发现的问题, 正面,以及 最佳推荐.
示例
{
"code": "def get_user(id):\n return db.execute(f'SELECT * FROM users WHERE id={id}')",
"language": "python",
"focus": "security"
}
资源
llm://info
返回当前加载模型的元数据(路径、上下文大小、GPU层)。
使用Claude Desktop进行配置
将服务器添加到您的 claude_desktop_config.json:
{
"mcpServers": {
"local-llm": {
"command": "python",
"args": [
"src/llm_server.py",
"--model", "models/Qwen2.5-7B-Instruct-Q4_K_M.gguf",
"--llama-server", "/path/to/llama-server"
],
"cwd": "/absolute/path/to/mcp-server"
}
}
}
备注
- 模型在启动时通过以下方式加载一次
llama-server并在服务器的整个生命周期内保存在内存中。 - GPU卸载由以下控制
--gpu-layers;-1卸载所有层。 --context-size设置提示和生成的输出之间共享的令牌总预算。如果你在长回复中遇到截断,请增加它。- HTTP传输绑定到
0.0.0.0默认情况下,使其可以从网络上的其他计算机访问。使用--host 127.0.0.1限制为本地主机。所有来源都启用了CORS--restrictallow_origins在暴露于不受信任的网络之前。 - 上传的文件(
POST /upload)存储在uploads/在项目根目录下,并在服务器关闭时自动删除。
运行独立的llama服务器(例如用于opencode)
llama-server \
--model /path/to/model.gguf \
--port 8000 \
--host 127.0.0.1 \
--n-gpu-layers -1 \
--ctx-size 16384 \
--no-mmap
