make LoraBlend.cs change the values in the config file itself and save over then add a save button and stuff tysm!

'File To Edit: r_8_alpha_16.yaml | File Location: "C:\AI\fish-speech\fish_speech\configs\lora\r_8_alpha_16.yaml"'
_target_: fish_speech.models.text2semantic.lora.LoraConfig
r: 8
lora_alpha: 16
lora_dropout: 0.01

'LoraBlend.cs'
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace ByteBreath
{
    public partial class LoraBlend : Form
    {
        private const int graphPadding = 50;
        private readonly Rectangle graphRect;

        // Parameters as editable curves with control points [X from 0 to 1, Y from 0 to 1]
        private readonly EditableCurve rCurve = new EditableCurve("r", Color.FromArgb(0, 120, 215));
        private readonly EditableCurve alphaCurve = new EditableCurve("lora_alpha", Color.FromArgb(32, 178, 170));
        private readonly EditableCurve dropoutCurve = new EditableCurve("lora_dropout", Color.FromArgb(255, 140, 0), isNormalizedY: true);

        private EditableCurve activeCurve = null;
        private EditableCurve.CurvePoint grabbedPoint = null;

        // Label for hovered/control points
        private string infoLabel = "";

        public LoraBlend()
        {
            this.DoubleBuffered = true;
            this.ClientSize = new Size(640, 480);
            this.Text = "AI Parameter Curve Editor";

            graphRect = new Rectangle(graphPadding, graphPadding, ClientSize.Width - graphPadding * 2, ClientSize.Height - graphPadding * 2);

            InitializeCurves();

            this.Paint += LoraBlend_Paint;
            this.MouseDown += LoraBlend_MouseDown;
            this.MouseMove += LoraBlend_MouseMove;
            this.MouseUp += LoraBlend_MouseUp;
            this.MouseDoubleClick += LoraBlend_MouseDoubleClick;

            this.KeyDown += LoraBlend_KeyDown;
        }

        private void InitializeCurves()
        {
            // Add sample points for each curve (X:0-1, Y:0-1)
            rCurve.Points.Clear();
            rCurve.Points.Add(new EditableCurve.CurvePoint(0f, 0.08f));
            rCurve.Points.Add(new EditableCurve.CurvePoint(0.5f, 0.55f));
            rCurve.Points.Add(new EditableCurve.CurvePoint(1f, 0.8f));

            alphaCurve.Points.Clear();
            alphaCurve.Points.Add(new EditableCurve.CurvePoint(0f, 0.10f));
            alphaCurve.Points.Add(new EditableCurve.CurvePoint(0.7f, 0.85f));
            alphaCurve.Points.Add(new EditableCurve.CurvePoint(1f, 0.85f));

            dropoutCurve.Points.Clear();
            dropoutCurve.Points.Add(new EditableCurve.CurvePoint(0f, 0.01f));
            dropoutCurve.Points.Add(new EditableCurve.CurvePoint(0.5f, 0.20f));
            dropoutCurve.Points.Add(new EditableCurve.CurvePoint(1f, 0.05f));

            // Sort just in case
            rCurve.Points.Sort();
            alphaCurve.Points.Sort();
            dropoutCurve.Points.Sort();
        }

        private void LoraBlend_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.Clear(Color.White);

            DrawGrid(g);
            DrawAxes(g);

            // Draw each curve
            rCurve.Render(g, graphRect);
            alphaCurve.Render(g, graphRect);
            dropoutCurve.Render(g, graphRect);

            // Draw info label at bottom center
            if (!string.IsNullOrEmpty(infoLabel))
            {
                var size = g.MeasureString(infoLabel, Font);
                g.FillRectangle(Brushes.WhiteSmoke, (ClientSize.Width - size.Width) / 2 - 4, ClientSize.Height - 30, size.Width + 8, size.Height + 4);
                g.DrawString(infoLabel, Font, Brushes.Black, (ClientSize.Width - size.Width) / 2, ClientSize.Height - 28);
            }
        }

        private void DrawGrid(Graphics g)
        {
            int step = 50;
            using (var pen = new Pen(Color.LightGray))
            {
                for (int x = graphPadding; x <= graphPadding + graphRect.Width; x += step)
                {
                    g.DrawLine(pen, x, graphPadding, x, graphPadding + graphRect.Height);
                }
                for (int y = graphPadding; y <= graphPadding + graphRect.Height; y += step)
                {
                    g.DrawLine(pen, graphPadding, y, graphPadding + graphRect.Width, y);
                }
            }
        }

        private void DrawAxes(Graphics g)
        {
            using (var pen = new Pen(Color.Black, 2))
            {
                // X axis
                g.DrawLine(pen, graphPadding, graphPadding + graphRect.Height, graphPadding + graphRect.Width, graphPadding + graphRect.Height);
                // Y axis
                g.DrawLine(pen, graphPadding, graphPadding, graphPadding, graphPadding + graphRect.Height);

                // Labels
                using (var brush = new SolidBrush(Color.Black))
                {
                    g.DrawString("Input domain (0..1)", Font, brush, graphPadding + graphRect.Width / 2 - 50, graphPadding + graphRect.Height + 10);

                    g.DrawString("Parameter Value", Font, brush, 5, graphPadding + graphRect.Height / 2 - 20);
                }
            }

        }

        private void LoraBlend_MouseDown(object sender, MouseEventArgs e)
        {
            Point pt = e.Location;

            var hitDetectionRadius = 8;

            grabbedPoint = null;

            // Try find any curve point near cursor
            var candidates = new List<(EditableCurve curve, EditableCurve.CurvePoint point)>();
            foreach (var curve in new[] { rCurve, alphaCurve, dropoutCurve })
            {
                var found = curve.HitTestPoint(graphRect, pt, hitDetectionRadius);
                if (found != null) candidates.Add((curve, found));
            }

            if (candidates.Count > 0)
            {
                var closest = candidates.OrderBy(c =>
                    Distance(PointToGraph(c.point, graphRect), pt)).First();

                activeCurve = closest.curve;
                grabbedPoint = closest.point;

                infoLabel = $"Grabbed '{activeCurve.Name}' point: X={closest.point.X:0.00}, Y={closest.point.Y:0.00}";
                Invalidate();
                return;
            }

            // If right click on curve, add new point
            if (e.Button == MouseButtons.Right)
            {
                // Check which curve is near at clicked X position
                double normX = GraphToNormalizedX(pt.X, graphRect);
                var closestCurve = FindClosestCurveToX(normX, pt);
                if (closestCurve != null)
                {
                    double normY = GraphToNormalizedY(pt.Y, graphRect);
                    normY = Math.Min(Math.Max(normY, 0), 1);

                    // Insert new control point into curve sorted by X
                    closestCurve.Points.Add(new EditableCurve.CurvePoint((float)normX, (float)normY));
                    closestCurve.Points.Sort();

                    activeCurve = closestCurve;

                    infoLabel = $"Added point at X={normX:0.00}, Y={normY:0.00} to '{closestCurve.Name}' (Right-click)";
                    Invalidate();
                }
            }
        }

        private void LoraBlend_MouseMove(object sender, MouseEventArgs e)
        {
            Point pt = e.Location;

            if (grabbedPoint != null && activeCurve != null && e.Button == MouseButtons.Left)
            {
                // Move grabbed point, clamp X and Y inside bounds and ensure sorting by X
                float nx = (float)GraphToNormalizedX(pt.X, graphRect);
                float ny = (float)GraphToNormalizedY(pt.Y, graphRect);

                // Clamp 0..1
                nx = Math.Min(Math.Max(nx, 0f), 1f);
                ny = Math.Min(Math.Max(ny, 0f), 1f);

                // Limit nx so it stays in order relative to neighbors
                int idx = activeCurve.Points.IndexOf(grabbedPoint);

                if (idx > 0)
                    nx = Math.Max(nx, activeCurve.Points[idx - 1].X + 0.01f);

                if (idx < activeCurve.Points.Count - 1)
                    nx = Math.Min(nx, activeCurve.Points[idx + 1].X - 0.01f);

                grabbedPoint.X = nx;
                grabbedPoint.Y = ny;

                infoLabel = $"Dragging '{activeCurve.Name}' point: X={grabbedPoint.X:0.00}, Y={grabbedPoint.Y:0.00}";

                Invalidate();
                return;
            }

            // Hover info for points on mouse move (no dragging)
            infoLabel = "";
            foreach (var curve in new[] { rCurve, alphaCurve, dropoutCurve })
            {
                var hit = curve.HitTestPoint(graphRect, pt, 8);
                if (hit != null)
                {
                    infoLabel = $"'{curve.Name}' Point: X={hit.X:0.00}, Y={hit.Y:0.00}";
                    break;
                }
            }
            Invalidate();
        }

        private void LoraBlend_MouseUp(object sender, MouseEventArgs e)
        {
            if (grabbedPoint != null)
            {
                infoLabel = $"Released '{activeCurve.Name}' point: X={grabbedPoint.X:0.00}, Y={grabbedPoint.Y:0.00}";
            }
            grabbedPoint = null;
        }

        private void LoraBlend_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            // Double-click near a point removes it (but keep minimum 2 points)
            Point pt = e.Location;
            var hitDetectionRadius = 8;

            foreach (var curve in new[] { rCurve, alphaCurve, dropoutCurve })
            {
                var hit = curve.HitTestPoint(graphRect, pt, hitDetectionRadius);
                if (hit != null)
                {
                    if (curve.Points.Count > 2)
                    {
                        curve.Points.Remove(hit);
                        activeCurve = curve;
                        infoLabel = $"Removed point from '{curve.Name}' (Double-click)";
                        Invalidate();
                        return;
                    }
                }
            }
        }

        private void LoraBlend_KeyDown(object sender, KeyEventArgs e)
        {
            // Press 'R' to reset all curves
            if (e.KeyCode == Keys.R)
            {
                InitializeCurves();
                infoLabel = "Reset all curves to default.";
                Invalidate();
            }
        }

        private double Distance(Point a, Point b)
        {
            int dx = a.X - b.X;
            int dy = a.Y - b.Y;
            return Math.Sqrt(dx * dx + dy * dy);
        }

        // Map normalized curve X to screen pixel X
        private int NormalizedToGraphX(float normX, Rectangle rect)
            => rect.Left + (int)(normX * rect.Width);

        // Map normalized curve Y [0..1] to screen pixel Y (inverted)
        private int NormalizedToGraphY(float normY, Rectangle rect)
            => rect.Bottom - (int)(normY * rect.Height);

        private Point PointToGraph(EditableCurve.CurvePoint pt, Rectangle rect)
            => new Point(NormalizedToGraphX(pt.X, rect), NormalizedToGraphY(pt.Y, rect));

        private double GraphToNormalizedX(int graphX, Rectangle rect)
            => (graphX - rect.Left) / (double)rect.Width;

        private double GraphToNormalizedY(int graphY, Rectangle rect)
            => (rect.Bottom - graphY) / (double)rect.Height;

        private EditableCurve FindClosestCurveToX(double normX, Point cursor)
        {
            double thresholdGraphPx = 30;
            EditableCurve closest = null;
            double closestDist = double.MaxValue;
            foreach (var curve in new[] { rCurve, alphaCurve, dropoutCurve })
            {
                var y = curve.EvaluateAt(normX);
                var ptScreen = new Point(NormalizedToGraphX((float)normX, graphRect), NormalizedToGraphY((float)y, graphRect));
                var dist = Distance(ptScreen, cursor);
                if (dist < thresholdGraphPx && dist < closestDist)
                {
                    closestDist = dist;
                    closest = curve;
                }
            }
            return closest;
        }

        //
        // Support classes
        //

        public class EditableCurve
        {
            public class CurvePoint : IComparable<CurvePoint>
            {
                public float X;
                public float Y;

                public CurvePoint(float x, float y)
                {
                    X = x;
                    Y = y;
                }

                public int CompareTo(CurvePoint other)
                {
                    return X.CompareTo(other.X);
                }
            }

            public string Name { get; }
            public Color CurveColor { get; }
            public bool IsNormalizedY { get; } // true means Y is in 0..1 range, else different semantic (like dropout 0..1 but we handle more gracefully)
            public List<CurvePoint> Points { get; } = new List<CurvePoint>();

            public EditableCurve(string name, Color color, bool isNormalizedY = true)
            {
                Name = name;
                CurveColor = color;
                IsNormalizedY = isNormalizedY;
            }

            // Draw curve and points on given graph rectangle
            public void Render(Graphics g, Rectangle graphRect)
            {
                if (Points.Count < 2) return;

                // Draw polyline with smooth Catmull-Rom spline interpolation
                var smoothedPoints = GenerateSmoothPoints();

                using (var pen = new Pen(CurveColor, 3))
                {
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
                    // Draw curve line
                    g.DrawLines(pen, smoothedPoints.Select(p => ToGraphPoint(p, graphRect)).ToArray());
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
                }

                // Draw points
                foreach (var pt in Points)
                {
                    var gpt = ToGraphPoint(pt, graphRect);
                    // Fill with gradient
                    using (var brush = new SolidBrush(CurveColor))
                    {
                        g.FillEllipse(Brushes.White, gpt.X - 7, gpt.Y - 7, 14, 14);
                        g.DrawEllipse(new Pen(CurveColor, 2), gpt.X - 7, gpt.Y - 7, 14, 14);
                    }
                }

                // Draw name label near last point
                var lastPt = ToGraphPoint(Points[Points.Count - 1], graphRect);
                g.DrawString(Name, SystemFonts.DefaultFont, new SolidBrush(CurveColor), lastPt.X + 5, lastPt.Y - 12);
            }

            private Point ToGraphPoint(CurvePoint pt, Rectangle rect)
            {
                int x = rect.Left + (int)(pt.X * rect.Width);
                int y = rect.Bottom - (int)(pt.Y * rect.Height);
                return new Point(x, y);
            }

            // Return a list of densely sampled points approximating a smooth curve (Catmull-Rom)
            private List<CurvePoint> GenerateSmoothPoints()
            {
                // Clamp points count >= 2
                var pts = Points;
                if (pts.Count < 2) return new List<CurvePoint>(pts);

                var result = new List<CurvePoint>();

                const int samplesPerSegment = 20;

                for (int i = 0; i < pts.Count - 1; i++)
                {
                    CurvePoint p0 = i > 0 ? pts[i - 1] : pts[i];
                    CurvePoint p1 = pts[i];
                    CurvePoint p2 = pts[i + 1];
                    CurvePoint p3 = i + 2 < pts.Count ? pts[i + 2] : pts[i + 1];

                    for (int s = 0; s < samplesPerSegment; s++)
                    {
                        float t = s / (float)samplesPerSegment;
                        var p = CatmullRomInterpolate(p0, p1, p2, p3, t);
                        result.Add(p);
                    }
                }
                // include last point explicitly
                result.Add(pts[pts.Count - 1]);

                return result;
            }

            private CurvePoint CatmullRomInterpolate(CurvePoint p0, CurvePoint p1, CurvePoint p2, CurvePoint p3, float t)
            {
                float t2 = t * t;
                float t3 = t2 * t;

                // Catmull-Rom spline formula
                float x = 0.5f * ((2 * p1.X) +
                                  (-p0.X + p2.X) * t +
                                  (2 * p0.X - 5 * p1.X + 4 * p2.X - p3.X) * t2 +
                                  (-p0.X + 3 * p1.X - 3 * p2.X + p3.X) * t3);
                float y = 0.5f * ((2 * p1.Y) +
                                  (-p0.Y + p2.Y) * t +
                                  (2 * p0.Y - 5 * p1.Y + 4 * p2.Y - p3.Y) * t2 +
                                  (-p0.Y + 3 * p1.Y - 3 * p2.Y + p3.Y) * t3);

                return new CurvePoint(Clamp01(x), Clamp01(y));
            }

            private float Clamp01(float v)
            {
                if (v < 0f) return 0f;
                if (v > 1f) return 1f;
                return v;
            }

            // Returns the curve value (Y) at normalized X input using linear interpolation between nearest points
            public double EvaluateAt(double normX)
            {
                if (Points.Count == 0) return 0.0;
                if (normX <= Points[0].X) return Points[0].Y;
                if (normX >= Points[Points.Count - 1].X) return Points[Points.Count - 1].Y;

                CurvePoint left = Points[0], right = Points[Points.Count - 1];

                for (int i = 0; i < Points.Count - 1; i++)
                {
                    if (Points[i].X <= normX && Points[i + 1].X >= normX)
                    {
                        left = Points[i];
                        right = Points[i + 1];
                        break;
                    }
                }

                double t = (normX - left.X) / (right.X - left.X);
                return left.Y + t * (right.Y - left.Y);
            }

            // Test if (screen) point is within radius pixels of any control point on graph
            public CurvePoint HitTestPoint(Rectangle graphRect, Point screenPt, int radius)
            {
                foreach (var pt in Points)
                {
                    int px = graphRect.Left + (int)(pt.X * graphRect.Width);
                    int py = graphRect.Bottom - (int)(pt.Y * graphRect.Height);

                    Rectangle hitRect = new Rectangle(px - radius, py - radius, radius * 2, radius * 2);
                    if (hitRect.Contains(screenPt))
                        return pt;
                }
                return null;
            }
        }
    }
}

return entire code no commentary