LINE bot for AI chat, image and video generation using Hugging Face models (ASP.NET / .NET 10)
C#
1
79 commits
updated Aug 21, 2026
English | 日本語
A LINE bot that uses Hugging Face models for AI chat, image generation, image editing, and video generation. Built on ASP.NET (.NET 10).
Try Hugging Face models casually through the LINE chat UI — no separate app or web console. The goal is to keep it easy to run: start the Docker image on your PC, expose it through a tunnel, and connect it to LINE (it can also be hosted in the cloud). Intended for evaluation and personal use, not as a multi-user service.
/image <prompt>, or switch to Image mode and just send a description/video <prompt> (text-to-video) and 🎬 Make a video from an image (image-to-video), both via the fal-ai provider. Off by default (App:VideoEnabled gates both) because fal-ai burns through Hugging Face credits fast and is slow; set it to true to enableApp:VisionEnabled=false a photo goes straight to editing.)HuggingFace:VisionModel). Each follow-up resends the image + prior turns, so cost grows with turns (capped by App:VisionMaxTurns)App:Locale = en/ja); user-facing text and the rich menu follow itSlash commands (/image, /video, /reset, /help) always work regardless of mode. The rich menu is
provisioned automatically on startup; set App:RichMenuEnabled=false to run without it.
LINE → POST /webhook (verify signature, return 200 immediately)
→ in-memory queue → background workers → Hugging Face
→ reply/push back to LINE (images are hosted at /media/{id})
LINE requires a public HTTPS URL for images, so the app hosts generated media itself and hands LINE the URL.
Built for easy, small-scale use — mind these trade-offs:
/media/{id}) live only in
process memory, with a TTL cache for media. They are lost on restart or redeploy. There is no database.The quickest path: run the published Docker Hub image locally and expose it with a tunnel — no source checkout or build needed. Other options are under Other ways to run.
devtunnel user login); ngrok or Cloudflare Tunnel work too.Do this first so you know the HTTPS URL before writing .env. Keep it running:
devtunnel host -p 8080 --allow-anonymous
Copy the https://…devtunnels.ms URL it prints — that's your App__PublicBaseUrl.
.envIn a new terminal, paste the tunnel URL into App__PublicBaseUrl and fill in your three tokens:
cat > .env <<'EOF'
Line__ChannelSecret=<your channel secret>
Line__ChannelAccessToken=<your channel access token>
HuggingFace__ApiKey=hf_xxxxxxxxxxxxxxxxx
App__PublicBaseUrl=https://<your-tunnel>.devtunnels.ms
EOF
Everything else has a sensible default. Full list: parameter reference.
docker pull pierre3/line-hf-bot:latest
docker run --env-file .env -p 8080:8080 pierre3/line-hf-bot:latest
Check it's up (in another terminal):
curl http://localhost:8080/health # -> {"status":"ok"}
Enable Use webhook (and turn off auto-reply) in the LINE console. Set the webhook URL to
https://<your-tunnel>.devtunnels.ms/webhook there, or use the line CLI
(Line.OpenApi.Tools, needs the .NET SDK):
dotnet tool install -g Line.OpenApi.Tools
line config set default --token "YOUR_CHANNEL_ACCESS_TOKEN"
line webhook set-endpoint --url "https://<your-tunnel>.devtunnels.ms/webhook"
line webhook test-endpoint
Add the bot as a friend (QR code in the LINE console) and message it. Full walkthrough, parameter reference, and troubleshooting: Run from Docker Hub.
Azure Container Apps — host on a managed HTTPS endpoint (no tunnel needed). One click, no CLI:
Fill in your three credentials in the browser. After it deploys, get the webhook URL from the deployment's Outputs tab (Resource group → Deployments → your deployment → Outputs, shown as lineWebhookUrl) — it isn't shown on the completion screen; you can also build it from the Container App's Application Url + /webhook. Register it in LINE. It runs as a single replica (max is always 1); with the default Minimum replicas = 1 it's always-on, so expect a small ongoing cost (pick 0 to scale to zero for trial use).
Run from source — build from a clone with Docker Compose or dotnet run, for development or customization.
| Input | Result |
|---|---|
| any text | interpreted by the current mode (chat / image / video) |
| a photo | the bot offers ✏️ Edit / 💬 Ask about this image / 🎬 Make a video (when video enabled); tap one, then your next message is applied (App:VisionEnabled=false → straight to editing) |
| a follow-up while asking | after a vision answer, plain messages keep asking about the same image in context; tap 💬 Chat (or switch mode) to leave |
/image <prompt> | generate an image |
/video <prompt> | generate a video (text-to-video via fal-ai); off by default, see App:VideoEnabled |
| 🎬 Make a video | turn the working image into a short clip (image-to-video via fal-ai); shown on image results and sent photos when App:VideoEnabled=true |
/reset | clear conversation history and reset mode |
/help | show usage |
Slash commands work in any mode without changing it. Image results carry 🔄 Regenerate / ✏️ Edit / 💬 Ask about this (when vision enabled) / 🎬 Make a video (when video enabled) / 💬 Chat buttons.
All settings are environment variables (Section__Key). See .env.example for the full list; the essentials:
| Variable | Notes |
|---|---|
Line__ChannelSecret / Line__ChannelAccessToken | LINE channel credentials (required) |
Line__MaxIncomingImageBytes / Line__ContentFetchTimeoutSeconds | limits for downloading a user-sent image to edit (default 10 MB / 30 s) |
HuggingFace__ApiKey | HF token with Inference Providers permission (required) |
HuggingFace__ChatModel | chat model, default Qwen/Qwen2.5-72B-Instruct (non-gated). Availability depends on your enabled Inference Providers — see Chat troubleshooting if replies fail |
HuggingFace__ImageEditModel / HuggingFace__ImageEditEndpoint | image-to-image via the fal-ai provider (default fal-ai/qwen-image-edit). hf-inference doesn't serve image-to-image; fal-ai costs more credits per call than hf-inference |
HuggingFace__VideoModel / HuggingFace__VideoEndpoint | text-to-video via the fal-ai provider (default fal-ai/wan/v2.2-5b/text-to-video). hf-inference doesn't serve text-to-video; fal-ai is credit-heavy and slow |
HuggingFace__ImageToVideoModel / HuggingFace__ImageToVideoEndpoint | image-to-video via the fal-ai provider (default fal-ai/wan/v2.2-a14b/image-to-video; lighter alternative fal-ai/wan-i2v). hf-inference doesn't serve image-to-video; A14B costs more credits than the 5B text-to-video default. Gated by App__VideoEnabled |
HuggingFace__VisionModel / HuggingFace__VisionEndpoint | vision Q&A for sent photos, via a vision chat model on the OpenAI-compatible endpoint. Uses chat-level HF credits (not fal). Pin the provider (model:provider) and enable it in HF settings — default Qwen/Qwen2.5-VL-72B-Instruct:ovhcloud needs ovhcloud enabled. See vision troubleshooting |
HuggingFace__MediaRefetchAllowedHosts | hosts allowed when re-fetching media from a provider URL (default fal.media;replicate.delivery; empty = deny all) |
App__PublicBaseUrl | your tunnel's HTTPS base (required for images) |
App__Locale | UI language for user-facing text and the rich menu (en default, or ja) |
App__RichMenuEnabled | provision the mode rich menu on startup (default true) |
App__VideoEnabled | enable video: /video (text-to-video) and 🎬 Make a video (image-to-video). Both run on the credit-heavy, slow fal-ai provider; default false |
App__VisionEnabled | vision Q&A on sent photos and generated images (default true). On: a sent photo offers Edit/Ask and image results add a 💬 Ask button; off: a sent photo goes straight to editing (no vision UI) |
App__VisionMaxTurns | max Q&A turns kept in a conversational vision session (default 8, min 1). Each follow-up resends the image + prior turns, so credit cost grows with turns — this caps it |
The "Ask about this image" answer is generated by a vision model on Hugging Face Inference Providers, so the reply depends on that provider serving the model for your token. If asking fails:
model_not_supported — auto-routing didn't pick a provider. Always pin the provider in HuggingFace__VisionModel as model:provider (e.g. Qwen/Qwen2.5-VL-72B-Instruct:ovhcloud) and enable that provider at https://huggingface.co/settings/inference-providers.capacity_exhausted (503) or timeout — the provider is busy or cold. Retry, or switch to another provider/model. Working alternatives: zai-org/GLM-4.5V:novita, google/gemma-3-27b-it:deepinfra (gemma requires accepting its license), Qwen/Qwen2.5-VL-7B-Instruct:featherless-ai. Enable the target provider first.HuggingFace__VisionTimeoutSeconds (default 120) bounds it.Chat runs through Hugging Face Inference Providers, so HuggingFace__ChatModel must be served by a provider your token has enabled. If the bot replies "Something went wrong" for plain messages, check the container logs — a model_not_supported / 400 from the router is the usual cause:
curl https://router.huggingface.co/v1/models -H "Authorization: Bearer <HF token>"
Then set HuggingFace__ChatModel to a served chat model (pin a provider as model:provider if needed) and enable providers at https://huggingface.co/settings/inference-providers.meta-llama/Llama-3.1-8B-Instruct, Qwen/Qwen3-4B-Instruct-2507. Avoid *-Coder (code-only) and *-VL (vision) models for general chat.Line.OpenApi.Bot)CHANGELOG.mddocs/deploy/ — Run from Docker Hub & LINE setup, Azure Container Apps, Run from sourcedocs/specs/ — 01 base bot, 02 image provider, 03 mode / rich menu / i18n, 04 editing user-sent photos, 05 image editing via fal-ai, 06 video via fal-ai, 07 image Q&A (vision/VQA), 08 image-to-video, 09 vision follow-up / multi-turndocs/reviews/CLAUDE.mdMIT.
C#
90.1%
PowerShell
6.4%
Bicep
2.8%
LINE bot for AI chat, image and video generation using Hugging Face models (ASP.NET / .NET 10)
C#
1
79 commits
updated Aug 21, 2026
English | 日本語
A LINE bot that uses Hugging Face models for AI chat, image generation, image editing, and video generation. Built on ASP.NET (.NET 10).
Try Hugging Face models casually through the LINE chat UI — no separate app or web console. The goal is to keep it easy to run: start the Docker image on your PC, expose it through a tunnel, and connect it to LINE (it can also be hosted in the cloud). Intended for evaluation and personal use, not as a multi-user service.
/image <prompt>, or switch to Image mode and just send a description/video <prompt> (text-to-video) and 🎬 Make a video from an image (image-to-video), both via the fal-ai provider. Off by default (App:VideoEnabled gates both) because fal-ai burns through Hugging Face credits fast and is slow; set it to true to enableApp:VisionEnabled=false a photo goes straight to editing.)HuggingFace:VisionModel). Each follow-up resends the image + prior turns, so cost grows with turns (capped by App:VisionMaxTurns)App:Locale = en/ja); user-facing text and the rich menu follow itSlash commands (/image, /video, /reset, /help) always work regardless of mode. The rich menu is
provisioned automatically on startup; set App:RichMenuEnabled=false to run without it.
LINE → POST /webhook (verify signature, return 200 immediately)
→ in-memory queue → background workers → Hugging Face
→ reply/push back to LINE (images are hosted at /media/{id})
LINE requires a public HTTPS URL for images, so the app hosts generated media itself and hands LINE the URL.
Built for easy, small-scale use — mind these trade-offs:
/media/{id}) live only in
process memory, with a TTL cache for media. They are lost on restart or redeploy. There is no database.The quickest path: run the published Docker Hub image locally and expose it with a tunnel — no source checkout or build needed. Other options are under Other ways to run.
devtunnel user login); ngrok or Cloudflare Tunnel work too.Do this first so you know the HTTPS URL before writing .env. Keep it running:
devtunnel host -p 8080 --allow-anonymous
Copy the https://…devtunnels.ms URL it prints — that's your App__PublicBaseUrl.
.envIn a new terminal, paste the tunnel URL into App__PublicBaseUrl and fill in your three tokens:
cat > .env <<'EOF'
Line__ChannelSecret=<your channel secret>
Line__ChannelAccessToken=<your channel access token>
HuggingFace__ApiKey=hf_xxxxxxxxxxxxxxxxx
App__PublicBaseUrl=https://<your-tunnel>.devtunnels.ms
EOF
Everything else has a sensible default. Full list: parameter reference.
docker pull pierre3/line-hf-bot:latest
docker run --env-file .env -p 8080:8080 pierre3/line-hf-bot:latest
Check it's up (in another terminal):
curl http://localhost:8080/health # -> {"status":"ok"}
Enable Use webhook (and turn off auto-reply) in the LINE console. Set the webhook URL to
https://<your-tunnel>.devtunnels.ms/webhook there, or use the line CLI
(Line.OpenApi.Tools, needs the .NET SDK):
dotnet tool install -g Line.OpenApi.Tools
line config set default --token "YOUR_CHANNEL_ACCESS_TOKEN"
line webhook set-endpoint --url "https://<your-tunnel>.devtunnels.ms/webhook"
line webhook test-endpoint
Add the bot as a friend (QR code in the LINE console) and message it. Full walkthrough, parameter reference, and troubleshooting: Run from Docker Hub.
Azure Container Apps — host on a managed HTTPS endpoint (no tunnel needed). One click, no CLI:
Fill in your three credentials in the browser. After it deploys, get the webhook URL from the deployment's Outputs tab (Resource group → Deployments → your deployment → Outputs, shown as lineWebhookUrl) — it isn't shown on the completion screen; you can also build it from the Container App's Application Url + /webhook. Register it in LINE. It runs as a single replica (max is always 1); with the default Minimum replicas = 1 it's always-on, so expect a small ongoing cost (pick 0 to scale to zero for trial use).
Run from source — build from a clone with Docker Compose or dotnet run, for development or customization.
| Input | Result |
|---|---|
| any text | interpreted by the current mode (chat / image / video) |
| a photo | the bot offers ✏️ Edit / 💬 Ask about this image / 🎬 Make a video (when video enabled); tap one, then your next message is applied (App:VisionEnabled=false → straight to editing) |
| a follow-up while asking | after a vision answer, plain messages keep asking about the same image in context; tap 💬 Chat (or switch mode) to leave |
/image <prompt> | generate an image |
/video <prompt> | generate a video (text-to-video via fal-ai); off by default, see App:VideoEnabled |
| 🎬 Make a video | turn the working image into a short clip (image-to-video via fal-ai); shown on image results and sent photos when App:VideoEnabled=true |
/reset | clear conversation history and reset mode |
/help | show usage |
Slash commands work in any mode without changing it. Image results carry 🔄 Regenerate / ✏️ Edit / 💬 Ask about this (when vision enabled) / 🎬 Make a video (when video enabled) / 💬 Chat buttons.
All settings are environment variables (Section__Key). See .env.example for the full list; the essentials:
| Variable | Notes |
|---|---|
Line__ChannelSecret / Line__ChannelAccessToken | LINE channel credentials (required) |
Line__MaxIncomingImageBytes / Line__ContentFetchTimeoutSeconds | limits for downloading a user-sent image to edit (default 10 MB / 30 s) |
HuggingFace__ApiKey | HF token with Inference Providers permission (required) |
HuggingFace__ChatModel | chat model, default Qwen/Qwen2.5-72B-Instruct (non-gated). Availability depends on your enabled Inference Providers — see Chat troubleshooting if replies fail |
HuggingFace__ImageEditModel / HuggingFace__ImageEditEndpoint | image-to-image via the fal-ai provider (default fal-ai/qwen-image-edit). hf-inference doesn't serve image-to-image; fal-ai costs more credits per call than hf-inference |
HuggingFace__VideoModel / HuggingFace__VideoEndpoint | text-to-video via the fal-ai provider (default fal-ai/wan/v2.2-5b/text-to-video). hf-inference doesn't serve text-to-video; fal-ai is credit-heavy and slow |
HuggingFace__ImageToVideoModel / HuggingFace__ImageToVideoEndpoint | image-to-video via the fal-ai provider (default fal-ai/wan/v2.2-a14b/image-to-video; lighter alternative fal-ai/wan-i2v). hf-inference doesn't serve image-to-video; A14B costs more credits than the 5B text-to-video default. Gated by App__VideoEnabled |
HuggingFace__VisionModel / HuggingFace__VisionEndpoint | vision Q&A for sent photos, via a vision chat model on the OpenAI-compatible endpoint. Uses chat-level HF credits (not fal). Pin the provider (model:provider) and enable it in HF settings — default Qwen/Qwen2.5-VL-72B-Instruct:ovhcloud needs ovhcloud enabled. See vision troubleshooting |
HuggingFace__MediaRefetchAllowedHosts | hosts allowed when re-fetching media from a provider URL (default fal.media;replicate.delivery; empty = deny all) |
App__PublicBaseUrl | your tunnel's HTTPS base (required for images) |
App__Locale | UI language for user-facing text and the rich menu (en default, or ja) |
App__RichMenuEnabled | provision the mode rich menu on startup (default true) |
App__VideoEnabled | enable video: /video (text-to-video) and 🎬 Make a video (image-to-video). Both run on the credit-heavy, slow fal-ai provider; default false |
App__VisionEnabled | vision Q&A on sent photos and generated images (default true). On: a sent photo offers Edit/Ask and image results add a 💬 Ask button; off: a sent photo goes straight to editing (no vision UI) |
App__VisionMaxTurns | max Q&A turns kept in a conversational vision session (default 8, min 1). Each follow-up resends the image + prior turns, so credit cost grows with turns — this caps it |
The "Ask about this image" answer is generated by a vision model on Hugging Face Inference Providers, so the reply depends on that provider serving the model for your token. If asking fails:
model_not_supported — auto-routing didn't pick a provider. Always pin the provider in HuggingFace__VisionModel as model:provider (e.g. Qwen/Qwen2.5-VL-72B-Instruct:ovhcloud) and enable that provider at https://huggingface.co/settings/inference-providers.capacity_exhausted (503) or timeout — the provider is busy or cold. Retry, or switch to another provider/model. Working alternatives: zai-org/GLM-4.5V:novita, google/gemma-3-27b-it:deepinfra (gemma requires accepting its license), Qwen/Qwen2.5-VL-7B-Instruct:featherless-ai. Enable the target provider first.HuggingFace__VisionTimeoutSeconds (default 120) bounds it.Chat runs through Hugging Face Inference Providers, so HuggingFace__ChatModel must be served by a provider your token has enabled. If the bot replies "Something went wrong" for plain messages, check the container logs — a model_not_supported / 400 from the router is the usual cause:
curl https://router.huggingface.co/v1/models -H "Authorization: Bearer <HF token>"
Then set HuggingFace__ChatModel to a served chat model (pin a provider as model:provider if needed) and enable providers at https://huggingface.co/settings/inference-providers.meta-llama/Llama-3.1-8B-Instruct, Qwen/Qwen3-4B-Instruct-2507. Avoid *-Coder (code-only) and *-VL (vision) models for general chat.Line.OpenApi.Bot)CHANGELOG.mddocs/deploy/ — Run from Docker Hub & LINE setup, Azure Container Apps, Run from sourcedocs/specs/ — 01 base bot, 02 image provider, 03 mode / rich menu / i18n, 04 editing user-sent photos, 05 image editing via fal-ai, 06 video via fal-ai, 07 image Q&A (vision/VQA), 08 image-to-video, 09 vision follow-up / multi-turndocs/reviews/CLAUDE.mdMIT.
C#
90.1%
PowerShell
6.4%
Bicep
2.8%